reactjs Redux即时更新

n7taea2i  于 2022-11-29  发布在  React
关注(0)|答案(2)|浏览(155)

考虑以下两种异径管:

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

还有:

const reducer = (state = initialState, action) => {
    switch(action.type){
        case 'changeName' :
          state.name = action.name
          return { ...state }
         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]);

假设这是一个在onClick上更改'toggle'的组件。如果我们使用第一个reducer,我们会得到以下输出:

name is: Joe name in redux is: Bob

name is: Bob name in redux is: Joe

这是因为组件必须重新呈现才能从redux获得更新的值。但是,如果我需要在同一个useEffect挂钩中从redux获得更新的值呢?我知道这是一个普通的例子,因为我在redux中设置它之前就知道它的名称。但假设我们从api中获取数据,我需要在同一个钩子中立即得到更新后的值,第二个reducer似乎解决了这个问题。它会打印:

name is: Joe name in redux is: Joe

name is: Bob name in redux is: Bob

但是,它是通过在发出具有更新状态的新对象之前直接更新redux状态来实现这一点的。(redux使用一个浅层比较来查看组件是否应该被重新渲染)然而,在第二个reducer中,我们实际上发出了一个全新的对象,但我们只是改变了之前的状态,以便立即更新值。
无论如何,我的问题是,这是否违反了我不知道的任何其他规则?实现第二个缩减器是否有任何错误?对我来说,这似乎是一个升级,因为我们在重新渲染之前和之后都得到了更新的值。

9jyewag0

9jyewag01#

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

不要直接操作状态

现在我们来讨论一个问题,如果你想在同一个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状态无论如何都会得到更新,在此之前,你可以使用在分派中使用的相同变量。

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]);
1mrurvl1

1mrurvl12#

我刚才也遇到了同样的问题,我的设置是:

export const enum LoadState {
    NotStarted,
    Loading,
    Loaded,
    Stale,
}

export type Loadable<T> = {
    state: LoadState;
    data: T;
};
  • CachingXProvider:我用它来请求某个react组件中的X的值,如果它已经被获取并存储在我的state中,我将它 Package 在Loadable中返回,state = Loaded。否则,我返回一个Loadable,state = Loading,在我的state中缓存这个正在加载的对象,并发出API请求以获取数据(在响应时,更新state中该高速缓存)。

我遇到了一个问题,在一个单一的呈现中,一个React组件会两次从缓存数据提供者请求一段数据。第二次请求会再次发出API请求,因为即使第一次请求调度了一个动作来更新redux状态,以记住我们已经请求了该项的事实,这意味该高速缓存将在第二次请求时丢失,并且将进行另一个API调用。
目前为止,我的解决方案是:让我的缓存数据提供程序保留它自己的静态项列表,这些项是它第一次从API请求的。如果在提供程序的生命周期中再次请求任何这样的项,则从该列表提供它。

相关问题