首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >useState对useReducer

useState对useReducer
EN

Stack Overflow用户
提问于 2019-02-12 09:19:13
回答 3查看 19.2K关注 0票数 33

当您有涉及多个子值的复杂状态逻辑时,或者当下一个状态依赖于前一个状态时,useReducer通常比useState更可取。useReducer还允许优化触发深度更新的组件的性能,因为可以传递分派而不是回调。

(引用自https://reactjs.org/docs/hooks-reference.html#usereducer)

我对粗体部分感兴趣,它指出在上下文中使用useReducer而不是useState

我尝试了这两种变体,但它们似乎并没有不同。

我比较这两种方法的方式如下:

代码语言:javascript
复制
const [state, updateState] = useState();
const [reducerState, dispatch] = useReducer(myReducerFunction);

我将它们中的每一个传递给一个上下文对象,这个对象在一个更深的子对象中使用(我只是运行单独的测试,用我想要测试的函数替换这个值)。

<ContextObject.Provider value={updateState // dispatch}>

这个孩子包含了这些功能

代码语言:javascript
复制
const updateFunction = useContext(ContextObject);
useEffect(
  () => {
    console.log('effect triggered');
    console.log(updateFunction);
  },
  [updateFunction]
);

在这两种情况下,当父级重新命名(因为另一个本地状态更改)时,效果都不会运行,这意味着更新函数在呈现之间没有改变。我读错了引文中的粗体句子吗?还是有什么东西我忽略了?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-02-12 09:25:25

useReducer还允许您优化触发深度更新的组件的性能,因为可以传递分派而不是回调。

上述语句并不试图表明useState返回的setter是在每次更新或呈现时新建的。它的意思是,当您有一个要更新状态的复杂逻辑时,您就不会直接使用setter来更新状态,而是编写一个复杂的函数,然后用更新的状态调用setter,类似于

代码语言:javascript
复制
const handleStateChange = () => {
   // lots of logic to derive updated state
   updateState(newState);
}

ContextObject.Provider value={{state, handleStateChange}}>

现在,在上述情况下,每次重新呈现父实例时,都会创建handleStateChange的新实例,从而导致上下文使用者也重新呈现。

解决上述情况的一个解决方案是使用useCallback并回溯状态更新器方法并使用它。但是,对于这一点,您需要处理与使用方法中的值相关的闭包问题。

因此,建议使用useReducer,它返回一个在重新呈现之间不发生更改的dispatch方法,并且您可以在还原器中使用操作逻辑。

票数 28
EN

Stack Overflow用户

发布于 2019-06-22 09:29:07

当你需要关心它的时候

如果在呈现时创建回调并将其传递给子组件,则该子组件的支持将发生更改。但是,当父组件呈现时,常规组件将重发(到虚拟区域),甚至道具也保持不变。例外是实现classComponent的shouldComponentUpdate,并比较道具(如PureComponent)。

这是一个优化,您应该只关心它,如果重命名子组件需要大量的计算(如果您将它多次呈现到同一个屏幕,或者它将需要一个深的或重要的改进机)。

如果是这样的话,您应该确保:

  1. 您的子类是扩展PureComponent的类组件。
  2. 避免将新创建的函数作为支柱传递。相反,传递调度时,setter从React.useState或自定义的回忆录setter返回。

使用回忆录自定义设置器

虽然我不建议为特定组件构建一个独特的回忆录设置器(您需要注意一些事情),但是您可以使用一个通用钩子来负责实现。

下面是一个useObjState钩子的例子,它提供了一个简单的API,并且不会导致额外的重发器。

代码语言:javascript
复制
const useObjState = initialObj => {
  const [obj, setObj] = React.useState(initialObj);
  const memoizedSetObj = React.useMemo(() => {
    const helper = {};
    Object.keys(initialObj).forEach(key => {
      helper[key] = newVal =>
        setObj(prevObj => ({ ...prevObj, [key]: newVal }));
    });
    return helper;
  }, []);
  return [obj, memoizedSetObj];
};

function App() {
  const [user, memoizedSetUser] = useObjState({
    id: 1,
    name: "ed",
    age: null,
  });

  return (
      <NameComp
        setter={memoizedSetUser.name}
        name={user.name}
      />
  );
}

const NameComp = ({name, setter}) => (
  <div>
    <h1>{name}</h1>
      <input
        value={name}
        onChange={e => setter(e.target.value)}
      />
  </div>
)

演示

票数 1
EN

Stack Overflow用户

发布于 2022-10-03 06:53:30

useReducer和useState -的实用观察

UseState:

在我的React中,我有一个屏幕,其中包含使用25+创建的不同状态。

我在useEffect (componentDidMount)中调用一个api,在获得基于某些条件的响应时,我将设置这25个状态,为每个函数调用25个状态设置函数。

我已经放置了一个重呈现计数器并检查了,我的屏幕是重新呈现的 times.

同样地,重呈现计数:

代码语言:javascript
复制
let count = 0;

export default function Home(props) {
  count++;
  console.log({count});
  //...
  // Rest of the code
 }

UseReducer :

然后,我在useReducer状态中移动了这25种状态,并且只使用一个操作来更新这些状态。

我观察到只有2次重呈现.

代码语言:javascript
复制
//API calling method:
    fetchData()
    {
     const response = await AuthAxios.getHomeData(); 
     dispatch({type: 'SET_HOME_DATA', data: response.data});
    
    }

//useReducer Code:
const initialStaes = {
  state1: null,
  state2: null,
   //.....More States 
  state27: null,
  state28: null
}

const HomeReducer = (state, action) => {
  switch (action.type) {
    case 'SET_HOME_DATA': {

      return {
        ...state,
        state1: (Data based on conditions),
        state2: !(some Conditions ),
        //....More states
        state27: false
       }
    }
  }
}

本例中useReducer的useReducer优势:

  1. 使用useReducer,我减少了屏幕上的重呈现次数,从而提高了应用程序的性能和流畅性。
  2. 我的屏幕本身减少了行数。它提高了代码的可读性。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54646553

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档