React面向组件跨层级通信
父与子
父组件包裹子组件,父组件向子组件传递数据。
1 | // 子 |
这样的通信方式非常适用于展示组件。
子与父
子组件存在于父组件之中,子组件需要向父组件传递数据。
- 回调函数(主要方式)
1 | // 子 |
实例函数(不符合 React 的设计理念,不被推荐)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23import React from 'react'
class HomePage extends React.Component {
modalRef = React.createRef() //实例
showModal = () ={
this.modalRef.show()
}
hideModal = () => {
this.modalRef.hide()
}
render() {
const {
text
} = this.state
return (
<>
<Button onClick={this.showModal}>展示 Modal </Button>
<Button onClick={this.hideModal}>隐藏 Modal </Button>
<Modal ref={modalRef} />
</>
/>
)
}
}兄弟
两个组件并列存在于父组件中,数据需要进行相互传递,往往依赖共同的父组件进行中转。
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// 子
class Input extends React.Component {
handleChanged = (e) => {
this.onChangeText(e.target.text)
}
render() {
return <input onChange={handleTextChanged} />
}
}
// 子
const StaticText = ({ children }) => {
return (
<P>{children}</p>
)
}
// 父
class HomePage extends React.Component {
state = {
text: '默认文案'
}
handleTextChanged = (text) => {
this.setState({
text,
})
}
render() {
return (
<>
<Input onChangeText={this.handleTextChanged} />
<StaticText>this.state.text</StaticText>
</>
)
}
}无直接关系
两个组件并没有直接的关联关系,处在一棵树中相距甚远的位置,但需要共享、传递数据。
Context
Context 第一个最常见的用途就是做 i18n- i18n使用Context
I18nContext
1
2
3
4
5
6
7import { createContext } from 'react';
const I18nContext = createContext({
translate: () => '',
getLocale: () => {},
setLocale: () => {},
});
export default I18nContext; - 用
I18nContext
封装个组件I18nProvider
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22import React, { useState } from 'react';
import I18nContext from './I18nContext';
class I18nProvider extends React.Component {
state = {
locale: '',
}
render() {
const i18n = {
translate: key => this.props.languages[locale][key],
getLocale: () => this.state.locale,
setLocale: locale => this.setState({
loacal,
})
}
return (
<I18nContext.Provider value={i18n}>
{this.props.children}
</I18nContext.Provider>
)
}
}
export default I18nProvider; - 用
I18nContext
实现高阶组件withI18n
1
2
3
4
5
6
7
8
9
10
11
12import React from 'react';
import I18nContext from './I18nContext';
const withI18n = () => {
return WrappedComponent => {
return (props) => (
<I18nContext.Consumer>
{i18n => <WrappedComponent {...i18n} {...props} />}
</I18nContext.Consumer>
)
}
};
export default withI18n; - 在最顶层注入 Provider
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { I18nProvider } from './i18n';
const locales = [ 'en-US', 'zh-CN' ];
const languages = {
'en-US': require('./locales/en-US'),
'zh-CN': require('./locales/zh-CN'),
}
ReactDOM.render(
<I18nProvider locales={locales} languages={languages}>
<App />
</I18nProvider>,
document.getElementById('root')
); - 在需要的地方使用
1
2
3
4
5
6
7
8
9
10
11
12const Title = withI18n(
({ translate }) => {
return ( <div>{translate('title')}</div> )
}
)
const Footer = withI18n(
({ setLocale }) => {
return ( <Button onClick=(() => {
setLocale('zh-CN')
}) /> )
}
)
- i18n使用Context
全局变量
全局变量,顾名思义就是放在 Window 上的变量。但值得注意的是修改 Window 上的变量并不会引起 React 组件重新渲染。状态管理框架
- Flux
- Redux
- Mobx
- 本文标题:React面向组件跨层级通信
- 本文作者:乔文飞
- 创建时间:2020-12-31 17:13:02
- 本文链接:http://www.feidom.com/2020/12/31/React面向组件跨层级通信/
- 版权声明:本博客所有文章为作者学习笔记,有转载其他前端大佬的文章。转载时请注明出处。