React组件间通信常见的几种情况:
- 父组件向子组件通信
- 子组件向父组件通信
- 跨级组件通信
- 非嵌套关系的组件通信
1. 父子组件的通信方式?
父组件向子组件通信:父组件通过 props 向子组件传递需要的信息。
// 子组件: Child
const Child = props =>{
return <p>{props.name}</p>
}
// 父组件 Parent
const Parent = ()=>{
return <Child name="react"></Child>
}
子组件向父组件通信:: props + 回调的方式。 具体来说,父组件可以将一个函数作为props传递给子组件,子组件在需要向父组件通信时,调用该函数并传递相应的数据作为参数。
// 父组件
function ParentComponent() {
function handleChildClick(data) {
console.log(`Received data from child component: ${data}`);
}
return (
<div>
<ChildComponent onClick={handleChildClick} />
</div>
);
}
// 子组件
function ChildComponent(props) {
function handleClick() {
const data = 'some data';
props.onClick(data);
}
return <button onClick={handleClick}>Click me</button>;
}
在上面的代码中,父组件定义了一个名为handleChildClick
的函数,并将其作为onClick
prop传递给子组件。子组件在按钮被点击时调用handleClick
方法,并传递一个字符串'some data'
作为参数,该参数会被传递到父组件中的handleChildClick
函数中,并在控制台中打印出来。这样就完成了子组件向父组件的通信。
2. 跨级组件的通信方式?
父组件向子组件的子组件通信,向更深层子组件通信:
- 使用 props,利用中间组件层层传递,但是如果父组件结构较深,那么中间每一层组件都要去传递props,增加了复杂度,并且这些 props 并不是中间组件自己需要的。
- 使用 context,context 相当于一个大容器,可以把要通信的内容放在这个容器中,这样不管嵌套多深,都可以随意取用,对于跨越多层的全局数据可以使用 context 实现。
创建一个名为UserContext的新上下文对象,并向其添加一个方法来更新用户信息:
import React, { createContext, useState } from 'react';
export const UserContext = createContext();
export const UserProvider = ({ children }) => {
const [user, setUser] = useState({
name: '',
email: '',
loggedIn: false,
});
const updateUser = (name, email) => {
setUser(prevState => ({
...prevState,
name,
email,
loggedIn: true,
}));
};
return (
<UserContext.Provider value={{ user, updateUser }}>
{children}
</UserContext.Provider>
);
};
在这里,我们使用useState hook创建了一个名为user的状态,它包含用户名、电子邮件和登录状态。然后,我们定义了一个名为updateUser的函数,它可以用于更新用户信息。
最后,我们使用createContext函数创建了一个名为UserContext的新上下文对象,并使用UserProvider组件将其提供给所有子组件。我们还将user和updateUser方法作为值传递给该提供程序组件。
现在,我们可以在任何组件中使用Consumer组件来访问该上下文:
使用useContext hook从UserContext中获取值,并将其解构为user和updateUser方法。
然后,我们可以使用它们来显示用户信息并更新用户信息。
import React, { useContext } from 'react';
import { UserContext } from './UserContext';
export const Profile = () => {
const { user, updateUser } = useContext(UserContext);
const handleUpdateUser = () => {
updateUser('John Doe', 'johndoe@gmail.com');
};
return (
<div>
<h2>User Profile</h2>
<p>Name: {user.name}</p>
<p>Email: {user.email}</p>
<button onClick={handleUpdateUser}>Update User</button>
</div>
);
};
3. 非嵌套关系组件的通信方式?
即没有任何包含关系的组件,包括兄弟组件以及不在同一个父级中的非兄弟组件。
- 可以使用自定义事件通信(发布订阅模式 event)
- 可以通过 redux 等进行全局状态管理
- 如果是兄弟组件通信,可以找到这两个兄弟节点共同的父节点, 结合父子间通信方式进行通信。
4. 如何解决 props 层级过深的问题
- 使用Context API:提供一种组件之间的状态共享,而不必通过显式组件树逐层传递props;
- 使用Redux等状态库。
5. 组件通信的方式有哪些
- ⽗组件向⼦组件通讯: ⽗组件可以向⼦组件通过传 props 的⽅式,向⼦组件进⾏通讯
- ⼦组件向⽗组件通讯: props + 回调的⽅式,⽗组件向⼦组件传递props进⾏通讯,此 props 为作⽤域为⽗组件⾃身的函 数,⼦组件调⽤该函数,将⼦组件想要传递的信息,作为参数,传递到⽗组件的作⽤域中
- 兄弟组件通信: 找到这两个兄弟节点共同的⽗节点,结合上⾯两种⽅式由⽗节点转发信息进⾏通信
- 跨层级通信: Context 设计⽬的是为了共享那些对于⼀个组件树⽽⾔是“全局”的数据,例如当前认证的⽤户、主题或⾸选语⾔,对于跨越多层的全局数据通过 Context 通信再适合不过
- 发布订阅模式: 发布者发布事件,订阅者监听事件并做出反应,我们可以通过引⼊ event 模块进⾏通信
- 全局状态管理⼯具: 借助 Redux 或者 Mobx 等全局状态管理⼯具进⾏通信,这种⼯具会维护⼀个全局状态中⼼ Store, 并根据不同的事件产⽣新的状态