玩React
那些日子。我知道setState
异步调用。但是像这样设置一个初始值:
const [data, setData] = useState(mapData(props.data))
它不应该直接更新吗?
下面是一个codeandbox来说明我当前的问题,这里是代码:
import React, { useState } from "react";
const data = [{ id: "LION", label: "Lion" }, { id: "MOUSE", label: "Mouse" }];
const mapData = updatedData => {
const mappedData = {};
updatedData.forEach(element => (mappedData[element.id] = element));
return mappedData;
};
const ChildComponent = ({ dataProp }) => {
const [mappedData, setMappedData] = useState(mapData(dataProp));
console.log("** Render Child Component **");
return Object.values(mappedData).map(element => (
<span key={element.id}>{element.label}</span>
));
};
export default function App() {
const [loadedData, setLoadedData] = useState(data);
const [filter, setFilter] = useState("");
const filterData = () => {
return loadedData.filter(element =>
filter ? element.id === filter : true
);
};
//loaded comes from a useEffect http call but for easier understanding I removed it
return (
<div className="App">
<button onClick={() => setFilter("LION")}>change filter state</button>
<ChildComponent dataProp={filterData()} />
</div>
);
}
所以,在我的理解,当我按一下按钮我打电话setFilter
所以App
应该重新呈现等ChildComponent
新过滤后的数据。
我可以看到它正在重新渲染并mapData(updatedData)
返回正确的过滤数据,但 ChildComponent
保留了旧的状态数据。
这是为什么 ?还是由于某种原因,它会重新渲染两次?
我知道我可以利用,useEffect(() => setMappedData(mapData(dataProp)), [dataProp])
但我想了解这里发生的事情。
编辑:我简化了很多代码,但是mappedData
在ChildComponent中必须处于状态,因为在我的实际用例中,它有时会被用户的操作更新
https://codesandbox.io/s/beautiful-mestorf-kpe8c?file=/src/App.js
该useState
钩得到的第一个初始化它的参数。因此,当再次调用该函数时,该挂钩始终产生原始集合。
顺便说一句,您不需要在那里的状态:
const ChildComponent = ({ dataProp }) => {
//const [mappedData, setMappedData] = useState(mapData(dataProp));
const mappedData = mapData(dataProp);
console.log("** Render Child Component **");
return Object.values(mappedData).map(element => (
<span key={element.id}>{element.label}</span>
));
};
编辑:这是一个修改后的版本,以保持useState
您所说的需要。不过,我不太喜欢此代码!:(
const ChildComponent = ({ dataProp }) => {
const [mappedData, setMappedData] = useState(mapData(dataProp));
let actualMappedData = mappedData;
useMemo(() => {
actualMappedData =mapData(dataProp);
},
[dataProp]
)
console.log("** Render Child Component **");
return Object.values(actualMappedData).map(element => (
<span key={element.id}>{element.label}</span>
));
};
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句