• React组件通信方式总结


    父组件向子组件传递数据

    无论是类组件还是函数式组件,父组件向子组件传递数据的方式都是使用 props 来实现的

    函数式组件:

    // 父组件
    import React from 'react';  
    import ChildComponent from './ChildComponent';  
    function ParentComponent() {  
      const message = 'Hello from Parent!';  
      return <ChildComponent message={message} />;  
    }  
    export default ParentComponent;  
    
    
    
    // 子组件(通过函数参数接收)
    import React from 'react';  
    function ChildComponent({ message }) {  
      return <div>{message}</div>;  
    }  
    export default ChildComponent;
    

    类组件:

    // 父组件
    import React from 'react';  
    import ChildComponent from './ChildComponent';  
    class ParentComponent extends React.Component {  
      render() {  
        const message = 'Hello from Parent!';  
        return (  
          <div>  
            <ChildComponent message={message} />  
          </div>  
        );  
      }  
    }  
    export default ParentComponent;
    
    
    
    // 子组件(通过 `this.props` 接收)
    import React from 'react';  
    class ChildComponent extends React.Component {  
      render() {  
        const { message } = this.props;  
        return (  
          <div>{message}</div>  
        );  
      }  
    }  
    export default ChildComponent;
    

    子组件向父组件传递数据

    无论是类组件还是函数式组件,子组件向父组件传递数据的方式都是通过 回调函数 来实现的

    • 父组件自定义函数,用来接收数据,并将函数通过 props 传递给子组件
    • 子组件调用父组件传递的函数并传递数据

    函数式组件:

    // 父组件
    import React from 'react';  
    import ChildComponent from './ChildComponent';  
    function ParentComponent() {  
    	const handleDataFromChild = (data) => {  
    	  console.log('Received data from child:', data);  
    	  // 在这里处理从子组件接收到的数据  
    	}  
    	return (  
    	  <div>  
    	    <ChildComponent onDataReceived={handleDataFromChild} />  
    	  </div>  
    	); 
    }  
    export default ParentComponent;  
    
    
    
    // 子组件
    import React from 'react';  
    function ChildComponent({ onDataReceived }) {  
      const handleClick = () => {  
        const data = 'Hello from Child!';  
        onDataReceived(data); // 调用父组件传递的回调函数并传递数据  
      }  
      return (  
        <button onClick={handleClick}>Send Data to Parent</button>  
      );  
    }  
    export default ChildComponent;
    

    类组件:

    // 父组件
    import React from 'react';  
    import ChildComponent from './ChildComponent';  
    class ParentComponent extends React.Component {  
      handleDataFromChild = (data) => {  
        console.log('Received data from child:', data);  
        // 在这里处理从子组件接收到的数据  
      }  
      render() {  
        return (  
          <div>  
            <ChildComponent onDataReceived={this.handleDataFromChild} />  
          </div>  
        );  
      }  
    }  
    export default ParentComponent;
    
    
    
    // 子组件
    import React from 'react';  
    class ChildComponent extends React.Component {  
      handleClick = () => {  
        const data = 'Hello from Child!';  
        this.props.onDataReceived(data); // 调用父组件传递的回调函数并传递数据  
      }  
      render() {  
        return (  
          <button onClick={this.handleClick}>Send Data to Parent</button>  
        );  
      }  
    }  
    export default ChildComponent;
    

    兄弟组件传递数据

    使用状态提升:父组件维护一个状态(state),这个状态将被传递给两个兄弟组件。

    兄弟A数据 => => 兄弟B数据

    1. 兄弟组件A:兄弟组件A通过向父组件传递数据
    2. 父组件:接收兄弟组件A传递过来的数据,并通过 props 传递给 兄弟组件B
    3. 兄弟组件B:接收父组件过来的数据,该数据即为兄弟组件A组件的数据

    函数式组件:

    // 父组件  
    import React, { useState } from 'react';  
    
    function ParentComponent() {  
      const [data, setData] = useState(null);  
      const handleDataChange = (newData) => {  
        setData(newData);  
      };  
      
      return (  
        <div>  
          <SiblingA onDataChange={handleDataChange} />  
          <SiblingB data={data} />  
        </div>  
      );  
    }  
      
    
    
    // 兄弟组件A  
    function SiblingA({ onDataChange }) {  
      // 假设这里有一个方法触发数据改变  
      const triggerDataChange = () => {  
        const newData = 'Hello from Sibling A!';  
        onDataChange(newData);  
      };  
      
      return (  
        <button onClick={triggerDataChange}>Send Data to Sibling B</button>  
      );  
    }  
      
    
    
    // 兄弟组件B  
    function SiblingB({ data }) {  
      return <div>{data}</div>;  
    }
    

    类组件:

    // 父组件  
    class ParentComponent extends React.Component {  
      state = { data: null };  
      handleDataChange = (newData) => {  
        this.setState({ data: newData });  
      };  
      render() {  
        return (  
          <div>  
            <SiblingA onDataChange={this.handleDataChange} />  
            <SiblingB data={this.state.data} />  
          </div>  
        );  
      }  
    }  
    
    
      
    // 兄弟组件A  
    class SiblingA extends React.Component {  
      // 假设这里有一个方法触发数据改变  
      triggerDataChange = () => {  
        const newData = 'Hello from Sibling A!';  
        this.props.onDataChange(newData);  
      };  
      render() {  
        return (  
          <button onClick={this.triggerDataChange}>Send Data to Sibling B</button>  
        );  
      }  
    }  
      
    
    
    // 兄弟组件B  
    class SiblingB extends React.Component {  
      render() {  
        return <div>{this.props.data}</div>;  
      }  
    }
    

    祖先与后代组件之间的传值

    使用 Context API

    在使用 React 的 Context API 时,通常会创建一个 Context 对象(例如 MyContext),然后在组件树中的某个位置使用 MyContext.Provider 来包裹那些需要访问 Context 值的组件

    • 这个 MyContext.Provider 通常会放在需要共享数据的最近公共祖先组件中。
    • 确保那些需要访问 Context 值的组件是 Context.Provider后代组件即可。
    // SiblingA、SiblingB 的公共祖先组件
    // 首先创建 Context  
    const MyContext = React.createContext();  
      
    // 创建一个 ProviderComponent 组件,它将使用 MyContext.Provider 来提供数据  
    function ProviderComponent() {  
      const [data, setData] = React.useState(null);  
    
      return (  
        <MyContext.Provider value={{ data, setData }}>  
          {/* 这里是子组件,包括 SiblingA 和 SiblingB,它们可以访问 MyContext 中的值 */}  
          <SiblingA />  
          <SiblingB />  
        </MyContext.Provider>  
      );  
    }  
      
    
    
    // SiblingA 组件
    function SiblingA() {  
      const { data } = React.useContext(MyContext);  // 使用 useContext 钩子来访问 MyContext 中的 data  
    
      return <div>SiblingA: {data}</div>;  
    }  
      
    
    
    // SiblingB 组件
    function SiblingB() {  
      const { setData } = React.useContext(MyContext);  // 使用 useContext 钩子来访问 MyContext 中的 setData  
      
      return (  
        <button onClick={() => setData('新的数据')}>Update Data in SiblingB</button>  
      );  
    }  
    
    1. { data, setData }}> 组件包裹住 组件,确保 是公共祖先组件
    2. 即可通过 React.useContext(MyContext) 获取到 MyContext 中的 valuesetData

    复杂关系的组件之间的传值

    使用发布-订阅模式

    当使用 发布-订阅模式 时,一般会使用第三方库 PubSubJS

    安装:
    npm install pubsub-js --save
    yarn add pubsub-js

    组件B传递数据给组件A:(即:组件A是订阅者,组件B是发布者,先订阅再发布)

    在组件A中:

    • 使用 PubSub.subscribe方法来订阅事件
    • 这个方法接受两个参数:事件名称和一个回调函数,该回调函数将在事件被发布时执行:
      import PubSub from 'pubsub-js;
      
      componentDidMount() {  
        // 订阅一个myEvent事件,当有发布myEvent事件时触发回调从而获取到发布的数据
        PubSub.subscribe('myEvent', (msg, data) => {  
          // 处理接收到的数据  
          console.log(msg, data);  // 'myEvent', { message: 'Hello from another sibling!' }
        });  
      }  
      
      componentWillUnmount() {  
        // 组件卸载时取消订阅,避免内存泄漏  
        PubSub.unsubscribe('myEvent', this.handleMyEvent);  
      }
      

    在组件B中:

    • 使用 PubSub.publish 方法来发布事件

    • 这个方法接受两个参数:事件名称和要传递的数据:

      import PubSub from 'pubsub-js;
      
      handleClick = () => {  
        // 发布一个myEvent事件,该事件和数据会被订阅myEvent事件的回调捕获
        PubSub.publish('myEvent', { message: 'Hello from another sibling!' }); 
      };  
      
      render() {  
        return (  
          <button onClick={this.handleClick}>Publish Event</button>  
        );  
      }
      

    注意:

    1. 当组件卸载时,记得取消订阅事件,以避免潜在的内存泄漏
    2. 通常不建议将其用作复杂关系组件之间传值的主要方式。React自身提供了一套基于 props 和 state 的数据流模型,以及 Context APIRedux 等库来处理更复杂的状态管理

    .

    使用 Redux

    Redux 是一个用于管理 JavaScript 应用程序中状态(state)的库,它提供了一种可预测的方式来更新应用程序的状态,类似 Vue 中的 Vuex

    传送门:

  • 相关阅读:
    servlet相关
    数据结构与算法:栈(java)
    【MM小贴士】关于MR21修改物料价格与账期的关系
    spring 5.1.x 本地构建 build.gradle文件配置
    软件工程评级B-,有大量调剂名额。北京联合大学考情分析
    基于JavaMaven+MySQL的网上B2C商城系统前后台设计
    【安全目标】
    SOCKS5代理与网络安全:如何安全地进行爬虫操作
    Mac下Tomcat服务器的使用-Tomcat服务器关闭
    【有问必答】搭建uniapp项目流程手把手教学
  • 原文地址:https://blog.csdn.net/x550392236/article/details/139599959