import React, { useState, useEffect } from "react";
export default function App() {
const [columns, setColumns] = useState([
{ name: "a" },
{ name: "b" },
{ name: "c" }
]);
const [isOpen, setIsOpen] = useState(false);
const addName = () => setColumns([...columns, { name: "r" }]);
const toggleOpen = () => setIsOpen(!isOpen);
return (
<>
<List columns={columns} />
<button onClick={toggleOpen}>Toggle</button>
<button onClick={addName}>Add</button>
<p>{isOpen.toString()}</p>
</>
);
}
const List = ({ columns }) => {
const names = columns.map(col => col.name);
useEffect(() => {
console.log("Names is changed to: ", names);
}, [names]);
return <p>{names.join(" ")}</p>;
};
在Names is changed to:
组件中更改isOpen
状态时,将调用 App
。
我希望仅在names数组更改时执行console.log
。
我认为在List
组件中,每当渲染时它都会创建一个新数组,以使先前的数组和新数组不相等。
答案 0 :(得分:3)
您should memoize the component,因此它将仅在道具更改时(或如果比较函数作为第二个参数传递时)呈现。
当前,List
的渲染是由于其父App
渲染。
const List = ({ columns }) => {
const names = columns.map((col) => col.name);
useEffect(() => {
console.log("Names is changed to: ", names);
}, [names]);
return <p>{names.join(" ")}</p>;
};
const MemoList = React.memo(List);
export default function App() {
return (
<>
<MemoList columns={columns} />
</>
);
}
请参见工作示例:
对于类组件,请使用React.PureComponent
或实现shouldComponentUpdate
。
答案 1 :(得分:3)
const names = columns.map(col => col.name);
每次创建一个新数组,useEffect
认为依赖关系已更改。
为避免这两种情况,请将names
直接传递给useEffect
:
useEffect(() => {
console.log("Names is changed to: ", names);
}, names);
或使用useMemo
获得相同的数组对象:
const names = useMemo(() => columns.map(
col => col.name
), [columns]);