React 组件间常用的数据通信方法
一、组件
1. 函数组件
函数组件是一个纯函数,使用普通函数或者箭头函数的方式来定义。
普通函数声名组件:
export default function Fn(props) {
return (
<div>
<h1>我是一个{ props.name }组件</h1>
</div>
)
}
箭头函数声明组件:
const Fn = (props) => {
return(
<div>
<h1>我是一个{ props.name }组件</h1>
</div>
)
}
export default Fn;
2. 类组件
通过 ES6 中的 class 语法的方式定义一个组件。
import React from "react";
export default class Class extends React.Component{
render() {
return (
<div>
<h1>我是一个{ this.props.name }组件</h1>
</div>
)
}
}
二、组件间的数据通信
父组件向子组件传递数据:
1. 通过 props 进行数据通信
函数组件
// 函数组件
import React from 'react';
function Welcome(props) {
return <h1>Hello, {props.name}!</h1>;
}
export default function App() {
return (
<div>
<Welcome name="Alice" />
<Welcome name="Bob" />
</div>
);
}
类组件
// 类组件
import React from 'react';
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
export default class App extends React.Component {
render() {
return (
<div>
<Welcome name="Alice" />
<Welcome name="Bob" />
</div>
);
}
}
2. 通过 Context 进行数据通信
函数组件
函数组件要在父组件或者全局声明 Context。之后把子组件用 <MyContext.Provider></MyContext.Provider>
包裹。数据通过 value
传递给子组件。在子组件中需要引入 Context 。之后定义一个变量,存储 useContext(MyContext)
这个钩子函数的结果。
// 父组件
import React from "react";
import Son from "./Son"
export const MyContext = React.createContext();
export default function Father() {
let name = "函数父亲";
return(
<MyContext.Provider value={ name }>
<Son></Son>
</MyContext.Provider>
)
}
// 子组件
import React, { useContext } from "react"
import { MyContext } from "./Father"
export default function Son() {
const fName = useContext(MyContext);
return (
<div>我是函数孩子,我有一个{ fName }</div>
)
}
类组件
与函数组件的方式类似,不过在子组件中要通过 <MyContext.Consumer>{(name) => <div>我有一个{ name }</div> }</MyContext.Consumer>
包裹要渲染的内容。
// 父组件
import React from "react";
import Son from "./Son";
export const MyContext = React.createContext();
export default class Father extends React.Component {
state = {
name : "父组件"
}
render() {
return (
<MyContext.Provider value={this.state.name}>
<Son></Son>
</MyContext.Provider>
)
}
}
// 子组件
import React from "react";
import { MyContext } from "./Father";
export default class Son extends React.Component{
render() {
return (
<MyContext.Consumer>
{(name) => <div>我有一个{ name }</div> }
</MyContext.Consumer>
)
}
}
3. 通过使用 state 进行数据通信
在父组件中创建名为 data 的状态,并把 data 的装填值和 setData 方法作为 props 传递给子组件。
在子组件Child
中使用props获取data
和setData
方法。当子组件中的按钮被点击时,调用setData
方法将数据更新并传递给父组件。
// 父组件
class Parent extends React.Component {
constructor(props) {
super(props);
this.state = {
data: ""
};
this.setData = this.setData.bind(this);
}
setData(data) {
this.setState({ data });
}
render() {
return (
<div>
<Child data={this.state.data} setData={this.setData} />
</div>
);
}
}
// 子组件
class Child extends React.Component {
handleClick() {
this.props.setData("Hello, World!");
}
render() {
return (
<div>
<p>Data from Parent: {this.props.data}</p>
<button onClick={this.handleClick.bind(this)}>Send Data to Parent</button>
</div>
);
}
}
4. 通过使用React Route 进行数据通信
如果在使用React Router库进行路由控制,那么可以通过路由参数将数据传递给子组件。
父组件使用Link
组件跳转到子组件,并通过state
属性将数据传递给子组件。子组件通过useLocation
钩子获取路由参数,并在页面上展示数据。
// Parent Component
function Parent() {
const message = "Hello, World!";
return (
<Link to={{ pathname: "/child", state: { message } }}>Go to Child</Link>
);
}
// Child Component
import { useLocation } from "react-router-dom";
function Child() {
const location = useLocation();
const message = location.state?.message;
return (
<div>{message}</div>
);
}
5. 通过使用 React Hook 进行数据通信
父组件可以使用React Hook(例如useState
、useEffect
等)来管理数据,然后将数据传递给子组件。
父组件使用 useState
钩子管理数据,并将数据通过props传递给子组件。
// Parent Component
function Parent() {
const [message, setMessage] = useState("Hello, World!");
return (
<Child message={message} />
);
}
// Child Component
function Child(props) {
return (
<div>{props.message}</div>
);
}
6. 通过使用 Reudx 进行数据通信
如果使用Redux进行状态管理,那么可以将需要传递给子组件的数据存储在Redux中,子组件可以通过Redux Store接收并使用这些数据。
父组件将数据存储在Redux Store中,并通过setMessage
action将数据设置为Redux Store中的状态。子组件通过useSelector
钩子获取Redux Store中的数据,并在页面上展示。
// Parent Component
function Parent() {
const message = "Hello, World!";
store.dispatch(setMessage(message));
return (
<Child />
);
}
// Child Component
import { useSelector } from "react-redux";
function Child() {
const message = useSelector((state) => state.message);
return (
<div>{message}</div>
);
}
子组件向父组件传递数据:
1. 通过 props 进行数据通信
// 子组件
import React from "react";
export default class Son extends React.Component{
constructor(props) {
super(props);
this.state = {
count: 0
}
}
handleClick= () => {
const newCount = this.state.count + 1;
this.setState({ count: newCount });
this.props.onCountChange(newCount);
}
render() {
return (
<div>
<h2>Child</h2>
<p>Count: { this.state.count }</p>
<button onClick={this.handleClick}>点击</button>
</div>
)
}
}
在例子中,定义了一个名叫 Son 的类组件,并在 handleClick 方法中,创建了一个 newCount 并对 state 进行了更新。通过调用 props.onCountChange 将newCount 传递给父组件。
// 父组件
import React from "react";
import Son from "./Son";
export default class Father extends React.Component{
handleCountChange = (newCount) => {
console.log(newCount);
}
render() {
return (
<div>
<Son onCountChange={ this.handleCountChange }></Son>
</div>
)
}
}
在例子中,定义了一个叫 Father 的类组件,并在 render 方法中渲染了 Son 组件。将父组件中定义的 handleCountChange 方法作为 props 属性传递给 Son 组件。并在 Son 组件中的 handleClick 方法中调用了这个方法,并将数据作为参数传递给父组件。
当 Son 组件中的按钮被点击的时候,会触发 handleClick 方法,该方法会通过 onCountChange 方法,将数据传递给父组件定义的 handleCountChange 方法。
2. 通过 Context 进行数据通信
函数组件
// 父组件
import React, { useState } from "react";
import Son from "./Son"
export const MyContext = React.createContext();
export default function Father() {
const [data, setData] = useState("");
return (
<MyContext.Provider value={ { data, setData } }>
<Son></Son>
</MyContext.Provider>
)
}
// 子组件
import React, { useContext } from "react"
import { MyContext } from "./Father"
export default function Son() {
const { data, setData } = useContext(MyContext);
function handleClick() {
setData("Hello, World!");
}
return (
<div>
<p>Data from Parent: {data}</p>
<button onClick={handleClick}>点击</button>
</div>
)
}
类组件
// 父组件
const MyContext = React.createContext();
class Parent extends React.Component {
constructor(props) {
super(props);
this.state = {
data: "",
setData: this.setData.bind(this)
};
}
setData(data) {
this.setState({ data });
}
render() {
return (
<MyContext.Provider value={this.state}>
<Child />
</MyContext.Provider>
);
}
}
// 子组件
class Child extends React.Component {
static contextType = MyContext;
handleClick() {
this.context.setData("Hello, World!");
}
render() {
const { data } = this.context;
return (
<div>
<p>Data from Parent: {data}</p>
<button onClick={this.handleClick.bind(this)}>Send Data to Parent</button>
</div>
);
}
}