React函数式组件通信方式

文件结构

  •  App.js
    // import StateHook from './components/StateHook';
    // import EffectHook from './components/EffectHook';
    // import LayoutEffectHook from './components/LayoutEffectHook';
    // import MemoHook from './components/MemoHook';
    // import CallbackHook from './components/CallbackHook';
    // import ReactMemo from './components/ReactMemo';
    // import RefHook from './components/RefHook';
    // import ForwardRefHook from './components/ForwardRefHook';
    // import ImperativeHandleHook from './components/ImperativeHandleHook';
    // import ContextHook from "./components/ContextHook";
    // import ReducerHook from "./components/ReducerHook";
    // import ObjectDemo from "./components/ObjectDemo";
    // import FromParentToSon from './components/FromParentToSon';
    // import FromSonToParent from './components/FromSonToParent';
    // import SkipLevel from './components/SkipLevel';
    // import BrotherComponent from './components/BrotherComponent';
    import PubSub from './components/PubSub';
    const App = () => {
      return (
        <div>
          {/* <StateHook></StateHook> */}
          {/* <EffectHook></EffectHook> */}
          {/* <LayoutEffectHook></LayoutEffectHook> */}
          {/* <MemoHook></MemoHook> */}
          {/* <CallbackHook></CallbackHook> */}
          {/* <ReactMemo></ReactMemo> */}
          {/* <RefHook></RefHook> */}
          {/* <ForwardRefHook></ForwardRefHook> */}
          {/* <ImperativeHandleHook></ImperativeHandleHook> */}
          {/* <ContextHook></ContextHook> */}
          {/* <ReducerHook></ReducerHook> */}
          {/* <ObjectDemo></ObjectDemo> */}
          {/* <FromParentToSon></FromParentToSon> */}
          {/* <FromSonToParent></FromSonToParent> */}
          {/* <SkipLevel></SkipLevel> */}
          {/* <BrotherComponent></BrotherComponent> */}
          <PubSub></PubSub>
        </div>
      );
    };
    
    export default App;
    

父子组件通信

父传子

主要通过属性传递的方式:

  • 使用
import { useState } from "react";
const FromParentToSon = () => {
  const [obj, setObj] = useState({ name: "w", age: 18 });
  const incrementAge = () => {
    setObj((prev) => {
      return { ...prev, age: prev.age + 1 };
    });
  };
  return (
    <div>
      <h1>
        From Father to Son--name:{obj.name}--age:{obj.age}
      </h1>
      <button onClick={incrementAge}>age+</button>
      <Child age={obj.age} />
    </div>
  );
};
const Child = (props) => {
  let { age } = props;
  return (
    <div>
      <h1>Son--age{age}</h1>
    </div>
  );
};

export default FromParentToSon;

子传父

通过调用父组件传递过来的方法,调用方法将参数传递出去

  • 使用
    import { useState } from "react";
    const FromSonToParent = () => {
      const [obj, setNum] = useState({ num: 0 });
      const handleClick = (age) => {
        setNum((prev) => {
          return {
            ...prev,
            num: age,
          };
        });
      };
    
      return (
        <div>
          <h6>parent--age:{obj.num}</h6>
          <Child handleClick={handleClick} />
        </div>
      );
    };
    const Child = (props) => {
      const { handleClick } = props;
      const [age, setAge] = useState(18);
      const handleDataToParent = () => {
        handleClick(age);
      };
      return (
        <div>
          <button onClick={handleDataToParent}>点我给父传数据</button>
          <button onClick={() => setAge(age + 1)}>点我改变年龄</button>
          <h6>child--age:{age}</h6>
        </div>
      );
    };
    export default FromSonToParent;
    

跨级组件

  • 介绍

对于跨级组件来说,可以采用层层传递属性的方式来实现组件之间的通信,但是当层级嵌套关系较深的时候,层层传递是比较繁琐且容易出错的,所以这里利用context来实现组件通信。组件层级关系App>SkipLevel>Child1>Child2>Child3。

  • 目录结构

  • 使用
  • userUseContext.js
import React from "react";
let UserContext = React.createContext();
export default UserContext;
  • SkipLevel/index.jsx
import React, { useState } from "react";
import Child1 from "./components/Child1";
import userUseContext from "./userUseContext";
const SkipLevel = () => {
  let object = {
    name: "w",
    age: 25,
  };
  let [obj, setObj] = useState(object);
  return (
    <div>
      <h6>parent--age{obj.age}</h6>
      <button onClick={() => setObj({ ...obj, age: ++obj.age })}>age+</button>
      <userUseContext.Provider value={obj.age}>
        <Child1></Child1>
      </userUseContext.Provider>
    </div>
  );
};
export default SkipLevel;
  • SkipLevel\components\Child1\index.jsx
import Child2 from "../Child2";
const Child1 = () => {
  return (
    <div>
      <Child2></Child2>
    </div>
  );
};
export default Child1;
  • SkipLevel\components\Child2\index.jsx
import Child3 from "../Child3";
const Child2 = () => {
  return (
    <div>
      <Child3></Child3>
    </div>
  );
};
export default Child2;
  • SkipLevel\components\Child3\index.jsx
import userUseContext from "../../userUseContext";
import { useContext } from "react";
const Child3 = () => {
  let user = useContext(userUseContext);
  console.log("user", user);
  return (
    <div>
      <h1>Child3</h1>
      <h2>user.age:{user}</h2>
    </div>
  )
};
export default Child3;

兄弟组件

  • 介绍

react的数据流是自顶向下的,无法通过react直接进行兄弟组件通信,通常是子组件向父组件传递数据,再有父组件告知另一个子组件。组件层级关BrotherComponent>Child1、Child2,组件BrotherComponent调用了组件Child1和组件Child2,组件Child1和Child2是兄弟组件。

  • 目录结构

  • 使用
  • BrotherComponent\index.jsx
import { useState } from "react";
import Child1 from "./components/Child1";
import Child2 from "./components/Child2";
const BrotherComponent = () => {
    let object = {
        num:0,
        name:"w"
    }
    const [obj,setObj] = useState(object)
    const IncrementAge = (value) => {
        setObj({...obj,num:obj.num+Number(value)})
    }
    return (
        <div>
            <h6>BrotherComponent--{obj.num}--{obj.name}</h6>
            <Child1 IncrementAge={IncrementAge}></Child1>
            <Child2 age={obj.num}></Child2>
        </div>
    )
    
}
export default BrotherComponent;
  • BrotherComponent\components\Child1\index.jsx
const Child1 = (props) => {
    let {IncrementAge} = props;
    return (
        <div>
            <h6>Child1</h6>
            <select onChange={(e)=>IncrementAge(e.target.value)}>
                <option value="1">+1</option>
                <option value="2">+2</option>
                <option value="3">+3</option>
            </select>
        </div>
    )
}
export default Child1;
  • BrotherComponent\components\Child2\index.jsx
const Child2 = (props) => {
    let {age} = props;
    return (
        <div>
            <h6>Child2--{age}</h6>
        </div>
    )
}
export default Child2;

任意组件之间


订阅发布模式

  • 首先,我们需要安装PubSub库:
npm install pubsub-js
  • 然后,让我们来看一个示例,展示如何在React应用中使用PubSub进行组件间的通信。
  • 目录结构

  • 使用
  • PubSub\index.jsx
import Child1 from "./components/Child1";
import Child4 from "./components/Child4";
const PubSub = ()=> {
    return (
        <div>
            <h1>PubSub</h1>
            <Child1></Child1>
            <Child4></Child4>
        </div>
    )
}
export default PubSub;
  • PubSub\components\Child1\index.jsx
import Child2 from '../Child2';
const Child1 = ()=> {
    return (
        <div>
            <h1>Child1</h1>
            <Child2></Child2>
        </div>
    )
}
export default Child1;
  • PubSub\components\Child2\index.jsx
import Child3 from '../Child3';
const Child2 = ()=> {
    return (
        <div>
            <h1>Child2</h1>
            <Child3></Child3>
        </div>
    )
}
export default Child2;
  • PubSub\components\Child3\index.jsx  发布消息的组件
import { useState } from "react";
import pubsub from "pubsub-js";
const Child3 = () => {
  let object = {
    name: "Child3",
    age: 30,
  };
  let [obj, setObj] = useState(object);
  const handleClick = () => {
    pubsub.publish("sendDateToBrother5", obj.age);
  };
  const IncreaseAge = () => {
    setObj((prev) => {
      return { ...prev, age: prev.age + 1 };
    });
  };
  return (
    <div>
      <h1>
        Child3--age{obj.age}--name{obj.name}
      </h1>
      <button onClick={IncreaseAge}>Age+</button>
      <button onClick={handleClick}>点我向五弟发送数据</button>
    </div>
  );
};
export default Child3;
  • PubSub\components\Child4\index.jsx
import Child5 from '../Child5';
const Child4 = ()=> {
    return (
        <div>
            <h1>Child4</h1>
            <Child5></Child5>
        </div>
    )
}
export default Child4;
  • PubSub\components\Child5\index.jsx 订阅消息的组件
import pubsub from "pubsub-js";
import { useEffect, useState } from "react";
const Child5 = () => {
  let [count, setCount] = useState(0);
  useEffect(() => {
    let test = pubsub.subscribe("sendDateToBrother5", (_, b) => {
      console.log("b", b);
    });
    console.log("test", test);
    return () => {
      pubsub.unsubscribe(test);
      console.log(777);
    };
  },[]);
  const handleClick = () => {
    setCount(count + 1);
  };
  return (
    <div>
      <h1>Child5--count{count}</h1>
      <button onClick={handleClick}>点击+1</button>
    </div>
    
  );
};
export default Child5;

通过这种消息订阅发布的模式,我们可以实现组件之间的解耦,使得它们能够独立地进行通信,而不需要直接引用彼此。这样的设计模式有助于提高代码的可维护性和可扩展性,使得应用程序更易于理解和维护。

  • 14
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值