你好,我有一个如下组件,我正在使用usestate钩子将myFeeds variabele初始化到feeds数组,并且正在运行一种效果,以从服务器(socket.io)添加任何数据。但是,当我进行控制台日志记录时结果myFeeds给我一个空数组,可能是什么原因?
const Dashboard = ({feeds}) => {
useEffect(() => {
getFeeds(); // this fetches feeds array
}, []);
const [myFeeds, setMyFeeds] = useState(feeds);
// useEffect hook to get real time messages and add it to feed
useEffect(() => {
let mount = true;
io.on('created' (data) => {
if(mount) {
data && setMyFeeds([...feeds, data]);
}
}
}, [])
console.log(feeds); // gives array of objects
console.log(myFeeds); // giving empty array
return(
<FeedBody body={myFeeds} />
);
}
// mapstatetoprops here
getFeeds是一个动作创建者,如下所示:
export const getFeeds = () => async dispatch => {
const res = await axios.get('/feeds');
// dispatch type get feeds here set payload to result of above operation
}
答案 0 :(得分:1)
我不知道这是否是问题,但是在使用feeds
道具并将其变成myFeeds
状态的过程中,这肯定是有问题的,几种方法:
如果父级使用新值再次调用它,则您的组件将看不到其feeds
道具的更新。请记住,传递给useState
的值仅在首次创建组件时使用,而在随后调用组件函数时不使用(而是使用组件的当前状态)
您在feeds
回调中使用的io.on
可能是过时的,因为您在useEffect
调用中有一个空的依赖项数组。到io.on
调用回调时,您的组件函数可能已被更新的feeds
调用(您会在console.log
中看到),但是与setMyData
一起使用的函数已被调用。将会是过时的(原始组件在第一次调用组件函数时被回调关闭)。
这就是我在#2中所指的内容:
useEffect(() => {
let mount = true;
io.on('created' (data) => {
if(mount) {
data && setMyFeeds([...feeds, data]);
// −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^^^^−−−−−−−−−−−− may be stale!
}
}
}, [])
您可能希望将io.on
调用移出该组件并将其放在父组件中,并在feeds
更改时让父组件重新渲染该组件。
如果您决定不这样做,则需要进行的最小更改是不使用该过时的feeds
参数值。而是使用回调形式:
useEffect(() => {
let mount = true;
io.on('created' (data) => {
if(mount) {
data && setMyFeeds(myFeeds => [...myFeeds, data]);
// −−−−−−−−−−−−−−−−−−−−−−−−−−−−^^^^^^^^−−−−−−−^^^^^^^−−−−−−−−−−−− up to date
}
}
}, [])
但是同样,您的组件将丢失对arent发送的feeds
的更新。
This note in the documentation关于使用钩子将道具复制到状态可能是有用的阅读。