如果有使用 eslint之類的工具,總是會在把 useEffect的 dependency補齊時發出警告
這裡我有個 list,需要在每次 props.data更新時同時更新 list
const [list, setList] = useState({});useEffect(() => { const newList = props.data.reduce((obj, item) => { obj[item.id] = list[item.id] || false; return obj; } , {}); setList(newList);}, [props.data]);
這時 eslint會提醒將 list加入 dependency中(而且是以紅字),但加入會發生什麼事?
}, [ list, props.data]);
在第一次觸發 useEffect
後,馬上因為呼叫了 setList
而再次觸發 useEffect
,就這樣一直無限循環,難道這裡只能拿掉 dependency了嗎?
當然最好不要,拿掉 dependency代表 list的值無法更新,可能會引起未知的 bug,這裡可以使用 useRef來解決
在 useEffect前使用 useRef來儲存舊的 list
const oldListRef = useRef();oldListRef.current = list;
然後在 useEffect中不使用 list,而是 oldListRef.current
useEffect(() => { const newList = props.data.reduce((obj, item) => { obj[item.id] = oldListRef.current[item.id] || false; return obj; } , {}); setList(newList);}, [props.data]);
這樣就可以讓 useEffect中可以拿到新的list值,也不會因為把list 加入dependency而進入無窮迴圈了
整體:
const [list, setList] = useState({});
const oldListRef = useRef();
oldListRef.current = list;useEffect(() => { const newList = props.data.reduce((obj, item) => { obj[item.id] = oldListRef.current[item.id] || false; return obj; } , {}); setList(newList);}, [props.data]);