React 父组件修改子组件的状态 vs 子组件修改父组件的状态

时隔多天,番茄又来更新了

内容简介

  1. React 父组件如何修改子组件的状态(state)
  2. React 子组件如何修改父组件的状态(state)

一、父组件修改子组件状态

可能的场景

  1. 控制子组件的表现 : 父组件可能需要控制子组件的显示或行为,例如,一个<Modal>组件的显示状态可能由父组件的一个按钮控制。
  2. 表单组件 : 在表单组件中,父组件可能需要重置表单字段,这时可以通过修改子组件的state来清空输入。
  3. 依赖于父组件的数据 : 如果子组件的状态依赖于父组件传递的props,父组件更新props时可能需要同时更新子组件的state

实现方法:使用Ref

虽然网上的方法有很多,但自我认为最实用的还是使用ref属性。举个例子🌰:

jsx 复制代码
// 父组件
export class ParentComponent extends React.Component {
  constructor(props) {
    super(props);
    // 创建一个ref来存储ChildComponent的引用
    this.childRef = React.createRef();
  }

  // 用于修改子组件state的方法
  changeChildState = () => {
    // 直接访问子组件的方法来更新其state
    if (this.childRef) {
      this.childRef.current.updateState("新的值");
    }
  };

  render() {
    return (
      <>
       <button onClick={this.changeChildState}>修改子组件状态</button>
       <br/>
       <br/>
        <ChildComponent ref={this.childRef} />
      </>
    );
  }
}

// 子组件
export class ChildComponent extends React.Component {
  state = {
    someState: '初始值'
  };

  // 子组件内部的方法来更新state
  updateState = (newValue) => {
    this.setState({ someState: newValue });
  };

  render() {
    return <div>我是子组件的state值:{this.state.someState}</div>;
  }
}

点击按钮修改子组件状态---->

在这个例子中,ParentComponent 创建了一个Refthis.childRef),并将其附加到子组件ChildComponent。然后,父组件可以通过this.childRef.current来访问子组件的方法和属性。changeChildState方法通过调用子组件的updateState方法来修改子组件的state。

注意: 这种方法应该谨慎使用,因为它可能导致难以追踪的bug和不可预测的行为。通常建议使用props和state来管理组件间的数据流。

二、子组件修改父组件的state

可能的场景

  1. 收集子组件的数据 : 父组件可能包含多个子组件,需要从每个子组件中收集数据,例如,一个调查问卷应用可能需要从多个<Question>组件中收集答案。
  2. 共享状态: 当多个子组件需要共享同一状态时,状态可以提升到它们的共同父组件中,子组件通过回调函数修改这个共享状态。
  3. 状态提升: 当某个状态需要在多个组件间共享或由多个组件影响时,通常会将状态提升到更高层级的组件中管理。

实现方法

1、回调函数

在React中,子组件可以通过调用从父组件传递下来的函数来修改父组件的state。这是一种常见的模式,允许子组件与父组件通信并触发状态更新。以下是一个简单的例子:

jsx 复制代码
// 父组件
 class ParentComponent extends React.Component {
  state = {
    parentState: '初始值'
  };

  // 用于被子组件调用以更新父组件state的函数
  updateParentState = (newState) => {
    this.setState({ parentState: newState });
  };

  render() {
    return (
      <>
      <div>我是父组件state:{this.state.parentState}</div>
      <br/>
      <ChildComponent updateParentState={this.updateParentState} />
      </>
    );
  }
}

// 子组件
class ChildComponent extends React.Component {
  // 当需要更新父组件的state时调用
  handleUpdate = () => {
    // 调用父组件传递的函数,并传递新的state值
    this.props.updateParentState('新的值');
  };

  render() {
    return (
      <button onClick={this.handleUpdate}>子组件按钮</button>
    );
  }
}

在这个例子中,ParentComponent 有一个名为 parentState 的state,它通过 updateParentState 函数来更新。这个函数被传递给 ChildComponent,子组件通过调用这个函数来更新父组件的state
点击按钮修改父组件状态---->

2、使用Context

众所周知,React的ContextAPI是一种非常强大的工具,它允许开发者跨越组件层级直接传递数据。下面是一个使用ContextAPI来实现父组件修改子组件state的示例:

jsx 复制代码
import React, { useState, useContext, createContext } from 'react';

// 创建一个Context对象
const MyContext = createContext();

// 父组件
const ParentComponent = () => {
  // 使用useState Hook来创建state和更新state的函数
  const [parentState, setParentState] = useState('初始值');

  return (
    // 使用MyContext.Provider来传递state和更新函数给子组件
    <MyContext.Provider value={{ parentState, setParentState }}>
      <ChildComponent />
    </MyContext.Provider>
  );
};

// 子组件
const ChildComponent = () => {
  // 使用useContext Hook来访问MyContext的值
  const { parentState, setParentState } = useContext(MyContext);

  return (
    <>
      <div>父组件的状态: {parentState}</div>
      <button onClick={() => setParentState('新的值')}>修改父组件状态</button>
    </>
  );
};

export default ParentComponent;

点击按钮修改父组件状态---->

在这个例子中,我们首先使用createContext创建了一个新的Context对象MyContext。然后,在ParentComponent中,我们使用useState Hook来创建一个state和一个更新这个state的函数。我们通过MyContext.Provider组件将这个state和函数传递给子组件。

ChildComponent中,我们使用useContext Hook来访问MyContext中的值,这包括父组件的state和更新函数。子组件可以使用这个更新函数来修改父组件的state

三、最后

想了解更多关于state的知识,可以查看React的官方文档组件间共享state

相关推荐
低代码布道师2 分钟前
CSS的三个重点
前端·css
耶啵奶膘2 小时前
uniapp-是否删除
linux·前端·uni-app
王哈哈^_^3 小时前
【数据集】【YOLO】【目标检测】交通事故识别数据集 8939 张,YOLO道路事故目标检测实战训练教程!
前端·人工智能·深度学习·yolo·目标检测·计算机视觉·pyqt
cs_dn_Jie4 小时前
钉钉 H5 微应用 手机端调试
前端·javascript·vue.js·vue·钉钉
开心工作室_kaic4 小时前
ssm068海鲜自助餐厅系统+vue(论文+源码)_kaic
前端·javascript·vue.js
有梦想的刺儿4 小时前
webWorker基本用法
前端·javascript·vue.js
cy玩具5 小时前
点击评论详情,跳到评论页面,携带对象参数写法:
前端
清灵xmf5 小时前
TypeScript 类型进阶指南
javascript·typescript·泛型·t·infer
小白学大数据5 小时前
JavaScript重定向对网络爬虫的影响及处理
开发语言·javascript·数据库·爬虫
qq_390161775 小时前
防抖函数--应用场景及示例
前端·javascript