背景:
在构建用户界面时,React 通过其组件化架构提供了一种高效的方式来组织代码。每个组件负责管理自己的状态和渲染逻辑,但随着应用的复杂性增加,组件之间需要共享数据和状态,或者需要触发彼此的操作。这就是组件通信发挥作用的地方。
为什么要实现组件通信?
- 数据共享:在多层嵌套的组件树中,有些数据需要在多个组件间共享
- 状态提升:在多层嵌套的组件结构中,如果深层组件需要修改上层组件的状态,这可能需要通过所谓的“状态提升”来实现,即将状态提升到它们共同的最近祖先组件中。
- 父子组件交互: 父组件可能需要获取子组件的数据或触发子组件的行为,反之亦然
- 兄弟组件通信:在某些情况下,两个兄弟组件(即共享同一父组件的组件)需要相互通信,但它们之间没有直接的父子关系
- 结耦组件:通过组件通信,可以减少组件间的直接依赖,使得组件更加独立和可复用
- 响应式更新:组件通信机制允许组件响应其他组件的状态变化,并根据需要更新自己的状态或UI
- 模式和最佳实践: 理解组件通信的模式和最佳实践可以帮助开发者编写更清晰、更可维护的代码
一、父子组件通讯(props)
父组件可以通过 ‘props’ 向子组件传递数据和函数。子组件可以通过调用传递的函数来与父组件通讯
父组件向子组件传递数据:
父传子:
1. 父组件传递数据,子组件标签身上绑定属性
2. 子组件接收数据 props 的参数
// PraentComponent.js
import React from 'react';
import ChildComponent from './ChildComponent'; // 引入子组件
function ParentComponent() {
const data = 'Hello from Parent';
return (
<div>
<ChildComponent message={data} />
</div>
);
}
export default ParentComponent;
// ChildComponent.js
import React from 'react';
function ChildComponent(props) {
return (
<div>
<p>{props.message}</p>
</div>
);
}
export default ChildComponent;
子组件向父组件传递数据
// ParentComponent.js
import React, { useState } from 'react';
import ChildComponent from './ChildComponent';
function ParentComponent() {
const [data, setData] = useState('');
const handleData = (childData) => {
setData(childData);
};
return (
<div>
<ChildComponent onData={handleData} />
<p>{data}</p>
</div>
);
}
export default ParentComponent;
// ChildComponent.js
import React from 'react';
const msg = 'Hello, 我是子组件的数据'
function ChildComponent(onData) {
const sendData = () => {
onData(msg)
};
return (
<div>
<button onClick={sendData}>Send Data</button>
</div>
);
}
export default ChildComponent;
二、兄弟组件通讯(通过父组件)
兄弟组件之间的通讯通常通过它们的共同父组件来进行。父组件管理共享状态,并将状态和更新函数通过 props
传递给子组件。
// APP.js
import React, { useState } from 'react';
import A from './A';
import B from './B';
function APP() {
const [name, setName] = useState('');
const getName = (name) => {
console.log(name)
setNAme(name)
}
return (
<div>
<A onGetAName={getName} />
<B data={sharedData} />
</div>
);
}
export default APP;
// A.js
import React from 'react';
function A({onGetAName}) {
const name = 'this is A name'
const updateData = () => {
onGetAName(name)
};
return (
<div>
<button onClick={updateData}>Update Data</button>
</div>
);
}
export default A;
// B.js
import React from 'react';
function B(name) {
return (
<div>
<p>{name}</p>
</div>
);
}
export default B;
三、使用Context API 实现跨层级传递
Context API 允许在组件树中传递数据而不必逐层传递 props
。这对于全局状态或配置特别有用。
import React from "react";
// 1. 使用createContext 创建一个上下文对象
const Context = React.createContext()
export default MyContext;
function App() {
const msg = 'this is app msg'
return (
// 2. 使用Provider组件包裹组件树,并传入value属性
<div>
<Context.Provider value={msg}>
this is app
<A />
</Context.Provider>
</div>
)
}
export default App;
function A() {
return <div>this is A</div>
}
export default A;
function B() {
// 3. 使用useContext获取上下文对象
const msg = useContext(Context)
return <div>this is B,{msg}</div>
}
export default B;