React父组件更新透传变量后子组件props值未同步更新问题
问题根源
- React 函数组件中普通的局部变量不具备响应性,你直接修改
let success = false这个变量不会触发父组件重渲染,因此父组件永远不会向子组件传递更新后的success值,子组件拿到的永远是初始值false。 - 即便你把变量改为响应式状态,子组件当前执行的
onSubmit函数因为闭包特性,拿到的永远是当前这一轮渲染传入的success值,就算父组件重渲染更新了prop,本次onSubmit作用域内的success也不会同步变化。
解决方法
第一步:将父组件的success改为响应式状态
用 React 内置的useState管理success变量,修改时调用状态更新函数触发父组件重渲染,才能把最新值传递给子组件。
修改后父组件核心代码:
import { useState } from 'react' function App() { // 替换普通let变量为useState状态 const [success, setSuccess] = useState(false) const changePW = async ({password, repeatPW}) => { // 你的密码修改逻辑写在这里 setSuccess(true) // 调用状态更新方法 console.log(`Success App0: ${success}`) console.log('ChangePW') // 可以直接把成功状态返回给子组件,不用等prop更新 return true } // 后面的渲染逻辑保持不变即可 return ( <BrowserRouter> <div className="container"> <Header/> <Route path='/' exact render={(props) => ( <> <AddPasswort onChange = {changePW} success = {success}/> <Footer /> </> )}/> <Route path='/about' component={About} /> <Route path='/success' component={Success} /> <Route path='/error' component={Error} /> </div> </BrowserRouter> ); } export default App;
第二步:调整子组件跳转逻辑
你可以直接拿onChange的返回值判断跳转,不用依赖prop,避免闭包问题,修改后子组件onSubmit代码:
const onSubmit = async (e) => { e.preventDefault(); const isSuccess = await onChange({password, repeatPW}) console.log(isSuccess) if (isSuccess){ console.log('success') history.push("/success") } else{ console.log('error') history.push("/error") } }
如果你确实需要依赖prop的success做其他逻辑,也可以用useEffect监听success变化来执行跳转:
const AddPasswort = ({onChange,success}) => { const[password, setPassword] = useState('') const[repeatPW, setRepeatPW] = useState('') const history = useHistory() // 监听success变化执行跳转 useEffect(() => { if(success) { history.push("/success") } }, [success, history]) const onSubmit = async (e) => { e.preventDefault(); await onChange({password, repeatPW}) } // 其余逻辑保持不变 }
内容的提问来源于stack exchange,提问作者Adrian
相关产品推荐
相关产品推荐

