簡體   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