React 组件通信

React 组件通信

一月 17, 2021

组件通信

在 ts 下的 react 组件通信, 需要给每个组件创建两个 interface 用于 ts 校验

父子通信

  1. 父组件绑定数据在子组件上
  2. 子组件通过 this.props 来接收数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import React, { Component } from "react";
import Hello from "./components/Hello";

interface P {
// P是constructor中的props参数
}

interface S {
// S是state数据
money: number;
}

export default class App extends Component<P, S> {
// <P,S>这样书写
constructor(props: P) {
// 这里
super(props);
this.state = {
money: 2000,
};
}
render() {
const { money } = this.state;
return (
<div>
<Hello money={money} />
</div>
);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import React, { Component } from "react";

interface P {
// 接收父组件传来的数据
money: number;
}

interface S {}

export default class Hello extends Component<P, S> {
render() {
return (
<div>
{this.props.money} {/* 用props来接收 */}
</div>
);
}
}

子父通信

  1. 父亲传递一个方法给子组件
  2. 子组件调用这个方法并传参
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
//App.tsx
/*
子父组件通信
父组件传递一个方法给子组件,
子组件调用这个方法,并且传递实参

*/
import React, { Component } from "react";
import Hello from "./components/Hello";

interface P {}

interface S {
xjk: number;
}

export default class App extends Component<P, S> {
constructor(props: P) {
super(props);
this.state = {
xjk: 2000,
};
}

setXjk = (val: number) => {
this.setState({
xjk: this.state.xjk + val,
});
};
render() {
const { xjk } = this.state;
return (
<div>
<Hello setXjk={this.setXjk} />
{xjk}
</div>
);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// Hello.ts
import React, { Component } from "react";

interface P {
setXjk: (val: number) => void;
}

interface S {
hongBao: number;
}

export default class Hello extends Component<P, S> {
constructor(props: P) {
super(props);
this.state = {
hongBao: 888,
};
}
count = 1;
sendHongBao = () => {
if (this.count > 1) return;
this.props.setXjk(this.state.hongBao);
this.count++;
};
render() {
return (
<div>
<button onClick={this.sendHongBao}>按钮</button>
</div>
);
}
}

非父子间通信

  1. 通过 ref 绑定获取 brother 组件中的 setCryFlag
  2. 绑定这个方法给 sister
  3. 形成非父子间通信
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// App.tsx
import React, { Component } from "react";
import Brother from "./components/Brother";
import Sister from "./components/Sister";

interface P {}

interface S {}

export default class App extends Component<P, S> {
brother: any = {};

kick = () => {
this.brother.setFlag();
};
render() {
return (
<div>
<Sister kick={this.kick} />
<Brother ref={(el) => (this.brother = el)} />
</div>
);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Brother.tsx
import React, { Component } from "react";

interface P {}

interface S {
flag: boolean;
}

export default class Brother extends Component<P, S> {
constructor(props: P) {
super(props);
this.state = {
flag: false,
};
}

setFlag = () => {
this.setState({
flag: !this.state.flag,
});
};
render() {
const { flag } = this.state;
return <div>{flag && "哭"}</div>;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Sister.tsx
import React, { Component } from "react";
interface P {
kick: () => void;
}
interface S {}

export default class Sister extends Component<P, S> {
render() {
return (
<div>
<button onClick={this.props.kick}>按钮</button>
</div>
);
}
}

跨组件通信

  1. 创建上下文对象
  2. 用 ctx.Provider 标签包裹 value 放数据
  3. 子孙组件通过 contextType 来接收 ctx 这个上下文对象
  4. 需要的子组件通过 this.context 直接使用

创建 context 文件夹并在里面放 index.ts

1
2
3
4
5
//todo 用于创建上下文对象
import React, { createContext } from "react";
const ctx: React.Context<number> = createContext(0);

export default ctx;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// App.tsx
import React, { Component } from "react";
import Father from "./components/Father";
import ctx from "./context"; // 引入ctx

interface P {}

interface S {
money: number;
}

export default class App extends Component<P, S> {
constructor(props: P) {
super(props);
this.state = {
money: 200000,
};
}
render() {
const { money } = this.state;
return (
<div>
<ctx.Provider value={money}>
{" "}
// 创建这个标签
<Father />
</ctx.Provider>
</div>
);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
// Father.tsx
import React, { Component } from "react";
import Son from "./Son";

export default class Father extends Component {
render() {
return (
<div>
<Son />
</div>
);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
// Son.tsx
import React, { Component } from "react";
import GrandSon from "./GrandSon";

export default class Son extends Component {
render() {
return (
<div>
<GrandSon />
</div>
);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// GrandSon
import React, { Component } from "react";
import ctx from "../context"; // 引入

export default class GrandSon extends Component {
static contextType = ctx; // 子孙组件通过contextType来接收ctx这个上下文对象
render() {
return (
<div>
{this.context} {/* 直接用this.context获取数据 */}
</div>
);
}
}