React onClick事件执行两个动作 先更新子组件再更新父组件state的方案
React onClick事件依次执行子组件state更新、父组件state更新的实现思路
以下是常用的3种落地实现方案:
思路1:利用setState的第二个回调参数(类组件适用)
- 类组件的
setState本身是异步批量更新的,它的第二个入参是state更新完成后才会触发的回调函数,刚好可以满足先更新子组件state、再执行父组件更新的顺序要求 - 代码示例:
class ChildComponent extends React.Component { state = { childCount: 0 } handleClick = () => { // 第一步:更新子组件自身state this.setState( { childCount: this.state.childCount + 1 }, // 第二步:子组件state更新完成后,调用父组件传入的更新方法 () => this.props.updateParentState(this.state.childCount) ) } render() { return <button onClick={this.handleClick}>点击按钮</button> } }
思路2:useEffect监听state变化(函数组件适用)
- 函数组件的
useState没有自带的回调参数,可以通过useEffect监听对应state的变化,state变更完成后自动触发父组件更新逻辑 - 代码示例:
import { useState, useEffect } from 'react' const ChildComponent = ({ updateParentState }) => { const [childCount, setChildCount] = useState(0) // 监听childCount变化,变更后执行父组件更新 useEffect(() => { // 可加判断跳过组件首次渲染的无效执行 if (childCount !== 0) { updateParentState(childCount) } }, [childCount, updateParentState]) const handleClick = () => { // 第一步:先更新子组件自身state setChildCount(prev => prev + 1) } return <button onClick={handleClick}>点击按钮</button> }
思路3:async/await封装state更新(类组件、函数组件通用)
- 可以把state更新封装成返回Promise的方法,用async/await严格控制执行顺序,适配所有组件写法
- 函数组件示例:
import { useState } from 'react' const ChildComponent = ({ updateParentState }) => { const [childCount, setChildCount] = useState(0) // 封装成Promise形式的更新方法 const updateChildState = (addVal) => { return new Promise(resolve => { setChildCount(prev => { const updatedCount = prev + addVal resolve(updatedCount) return updatedCount }) }) } const handleClick = async () => { // 第一步:等待子组件state更新完成 const updatedCount = await updateChildState(1) // 第二步:更新父组件state updateParentState(updatedCount) } return <button onClick={handleClick}>点击按钮</button> }
注意事项
- 不要直接在
setState/useState调用后立刻写父组件更新逻辑,React的异步更新机制会导致你拿到的还是更新前的旧state值 - 如果父组件更新不需要依赖子组件更新后的最新state,不需要严格卡执行顺序,按逻辑先后写即可,React的更新队列会保证先触发的更新先执行
内容的提问来源于stack exchange,提问作者abrahampromise
相关产品推荐
相关产品推荐

