Reactjs Redux即时更新

Reactjs Redux即时更新,reactjs,redux,react-hooks,Reactjs,Redux,React Hooks,考虑这两个减速器: const reducer = (state = initialState, action) => { switch(action.type){ case 'changeName' : return { ...state, name: action.name } default: return state } } 以及: 假设我们有一个带有以下钩子的react组件: co

考虑这两个减速器:

const reducer = (state = initialState, action) => {
    switch(action.type){
        case 'changeName' :
          return { ...state, name: action.name }
         default:
           return state 
    }
}
以及:

假设我们有一个带有以下钩子的react组件:

  const reduxState = useSelector(state=>state)

  const [toggle,setToggle] = useState(false)

  React.useEffect(() => {
      const name = toggle?'Joe':'Bob'
      dispatch({type: 'changeName', name}));
      console.log('name is:', name, 'name in redux is:', reduxState.name)
 }, [toggle]);
假设这是在一个组件中,它在单击时改变了“toggle”。如果我们使用第一个减速器,我们将获得以下输出:

name is: Joe name in redux is: Bob

这是因为组件必须重新加载,我们才能从redux获得更新的值。但是,如果我需要在同一个useffect钩子中使用redux的更新值呢。我知道这是一个很小的例子,因为我在redux中设置它之前就知道它的名称,但是假设我们从一个api获取数据,我需要在同一个钩子中立即更新值。第二个减速器似乎解决了这个问题。它打印:

name is: Joe name in redux is: Joe

但是,它是通过在发出具有更新状态的新对象之前直接更新redux状态来实现的。Redux文档声明决不应直接更新Redux状态,但这是因为它阻止组件订阅Redux状态中的更改(Redux使用浅层比较来查看组件是否应重新提交)。然而,在第二个reducer中,我们实际上发出了一个全新的对象,但我们只是直接改变之前的状态,以便立即更新值


不管怎样,我的问题是,这是否违反了我不知道的其他规则?使用第二个减速器是否有任何错误?对我来说,这似乎是一种升级,因为我们在重新加载之前和之后都会得到更新的值。

第二个减速机正在做你想做的事情,因为它直接操纵状态,这是一种非常糟糕的做法

切勿直接操纵状态

现在进入问题,如果您希望数据具有相同的useEffect,该怎么办。如果您正在useEffect中设置状态,并且希望该状态返回到相同的useEffect中,那么您可以直接使用数据,而无需从该状态获取数据

考虑到您的示例,理想的实现应该是:

  const reduxState = useSelector(state=>state)
  const [toggle,setToggle] = useState(false)

  React.useEffect(() => {
      const name = toggle?'Joe':'Bob'
      dispatch({type: 'changeName', name}));
      console.log('name is:', name);
 }, [toggle]);

  React.useEffect(() => {
      console.log('name in redux is:', reduxState.name);
 }, [reduxState.name]);

虽然您说过,您需要在相同的useEffect中使用数据,但要做到这一点,您可以直接使用变量。redux状态无论如何都会得到更新,在此之前,您可以使用在dispatch中使用的相同变量

  const reduxState = useSelector(state=>state)

  const [toggle,setToggle] = useState(false)

  React.useEffect(() => {
      const name = toggle?'Joe':'Bob'
      dispatch({type: 'changeName', name}));
      console.log('name is:', name, 'name in redux is:', name)
 }, [toggle]);
 

Redux更新的唯一来源是通过订阅存储。如果需要,您可以在action creator中返回资源的表示形式(如ID),但不可以-当您记录名称时,不可能返回下一个状态的全部或部分。如果我需要useEffect中的数据,但我事先不知道数据是什么,就像它来自一个外部api,而我的调度是一个thunk。另外,如果我在下一行立即替换状态,为什么直接更新状态是一种不好的做法?直接更新状态是一种不好的做法,因为状态是一个被引用的对象。你可以参考这篇文章来了解我要解释的内容。关于这件事,你正在努力实现。如果你有一个直接改变状态是前进的唯一途径的例子,那肯定是出了问题。如果你能发布准确的场景,我可以帮你解决。我正在尝试处理的场景是,当我需要调用一个thunk,它需要之前调用的thunk中的数据…而不需要在同一个thunk中放入多个回迁。
name is: Bob name in redux is: Bob
  const reduxState = useSelector(state=>state)
  const [toggle,setToggle] = useState(false)

  React.useEffect(() => {
      const name = toggle?'Joe':'Bob'
      dispatch({type: 'changeName', name}));
      console.log('name is:', name);
 }, [toggle]);

  React.useEffect(() => {
      console.log('name in redux is:', reduxState.name);
 }, [reduxState.name]);

  const reduxState = useSelector(state=>state)

  const [toggle,setToggle] = useState(false)

  React.useEffect(() => {
      const name = toggle?'Joe':'Bob'
      dispatch({type: 'changeName', name}));
      console.log('name is:', name, 'name in redux is:', name)
 }, [toggle]);