繁体   English   中英

依赖值更改时 useEffect 不起作用

[英]useEffect not working when dependency value changed

我从 React hook 体验过 useEffect 函数。 当我将它与 React-redux 的 useSelector 一起使用时,它工作得非常奇怪。

我的减速机:

const initialState = { a: 0 };

function mainReducer(state = initialState, action) {
  const { type, payload } = action;
  switch (type) {
    case 'A': return { ...state, a: payload }
    default:
      return state;
  }
}

我的组件:

function MyComponent(props) {
  const { a } = useSelector(state => state.mainReducer);
  const dispatch = useDispatch(); 
  
  useEffect(() => {
    console.log('did mount: ', a);
    dispatch({ type: 'A', payload: 1 })
  }, []); 

  useEffect(() => {
    console.log('use effect: ', a);
    dispatch({ type: 'A', payload: a });
  }, [a]) 

  return (<View style={styles.container}>
    <Text style={styles.text}>{a}</Text>
  </View>);
};

结果

日志:

did mount ran: 0
useEffect ran: 0

最后的结果是变量 'a' = 0

???

据我了解,在第一次渲染之后,这两种效果都按照代码中的顺序依次运行。
(步骤 1) 所以第一个效果 run fist -> log 'did mount ran: 0'。 然后它调度值 1 来存储
(步骤 2)第二个效果运行 -> 记录 'did mount ran: 0'。 然后它调度值 0 来存储

但我不明白的是,第二个效果必须跟踪变量“a”的变化,所以会有:
在以下渲染时间:
(第 3 步)当值“a”从 0 变为 1(从第 1 步开始)时,应该运行第二个 useEffect。
进而:
(第 4 步)当值再次从 1 变为 0 时(从第 2 步开始),它应该进行第三次重新渲染

所以日志应该是:

did mount ran: 0
useEffect ran: 0
useEffect ran: 1
useEffect ran: 0

你能向我解释一下我错过了什么吗? 谢谢

您的两个调度在第一次渲染之后被调用,因此即使在您的第二个渲染值为 0 之前,您的第二个 useEffect 将无法检测到变化,因为没有变化。

让我们看看渲染方法中发生了什么

第一次渲染:

一 = 0

第一个 useEffect: dispatch({ a : 1 })

第二个 useEffect: dispatch({ a : 0 })

所以现在在你的 redux store 中 a 是 0。

第二次渲染

一 = 0

first useEffect: 不运行,因为没有依赖

第二个 useEffect: 不会因为 hans's 没有改变而运行。

请停止使用

 useSelector(state => state.mainReducer);

没有任何意义

应该有一个简单的状态转换(子选择)

const a = useSelector(state => state.a)

直接取自 redux 文档:

const counter = useSelector(state => state.counter)  

更新

你可以看到效果(从商店变化)略有变化的组件

function MyComponent(props) {
  const a = useSelector(state => state.a);
  const dispatch = useDispatch(); 

  console.log('render: ', a);

  useEffect(() => {
    console.log('use effect: ', a);
    dispatch({ type: 'A', payload: a });
  }, [a]) 

  useEffect(() => {
    console.log('did mount: ', a);
    dispatch({ type: 'A', payload: 1 })
  }, []); 

  return (<View style={styles.container}>
    <Text style={styles.text}>{a}</Text>
  </View>);
};

它应该导致日志:

  • render: 0 // 初始状态
  • use effect: 0 // 第一个效果运行
  • // dispatch 0 ... 在 store 中被 reducer 处理,但结果是相同的状态 ...
    // ...在我们的渲染过程中,我们仍在处理一个“旧的” a在渲染开始时从状态中读取
  • did mount: 0 // '旧' a
    // dispatch 1 ... 在 redux 存储中改变状态
  • .... 渲染文本0
    ...
    ...

  • // useSelector强制重新渲染 - 检测到更改

  • render: 1 // 最新调度的值,由reducers 处理成新状态,由选择器重读
  • use effect: 1 // useEffect作品如预期的效果a变化
  • .... 渲染文本1

...
...

  • 不再重新渲染 - 最新调度未更改状态

当然,来自其他组件的调度将强制在该组件中进行更新......如果值会不同。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM