React中使用useState与Context Api无法复制状态数组到另一状态数组
问题分析与解决方案
嘿,我瞅了下你的代码,问题主要出在这几个地方,咱们一步步来改:
1. 第一个useEffect的依赖错误
你写的依赖是[restMovies.values],但restMovies是个数组,根本没有values属性呀!而且这个请求只需要在组件挂载时执行一次,所以依赖应该是空数组[],不然要么不会触发请求,要么可能导致无限请求循环。
2. 第二个useEffect的双重问题
- 依赖错误:同样用了
movies.values和restMovies.values,这俩都是不存在的属性,正确的依赖应该是[restMovies]——只有当restMovies的数据更新时,我们才需要同步到movies里。 - 循环更新
movies的方式错误:你用map循环调用setMovies([...movies, item]),这里的movies是闭包捕获的初始空数组,所以每次循环都是把当前item放到空数组里,最后只会留下最后一个元素,而且多次调用setMovies还会导致不必要的重复渲染。
修正后的完整代码
import { createContext, useState, useEffect } from 'react'; import axios from 'axios'; export const MoviesContext = createContext(); export const MoviesContextProvider = (props) => { const [restMovies, setRestMovies] = useState([]); const [movies, setMovies] = useState([]) // 只在组件挂载时请求一次数据 useEffect(() => { axios.get("https://api.tvmaze.com/shows").then(resp => setRestMovies(resp.data)); }, []); // 当restMovies更新时,同步到movies数组 useEffect(() => { // 确保restMovies有数据再更新 if (restMovies.length) { // 用扩展运算符做浅拷贝,或者直接setMovies(restMovies)(如果不需要修改原数组的话) setMovies([...restMovies]); } }, [restMovies]); // 如果后续需要修改movies,建议把setMovies也放进Context里,方便子组件调用 return ( <MoviesContext.Provider value={{ movies, setMovies }}> {props.children} </MoviesContext.Provider> ) }
额外小建议
你原来的Context value只传了[movies],如果后续需要在子组件里修改movies的话,最好把setMovies也传进去,像上面代码那样用对象传递,可读性更强。
内容的提问来源于stack exchange,提问作者Hadar Rosenman
相关产品推荐
相关产品推荐

