在大型项目中公共信息(语言、主题) 如何传递给每个组件?
用props过于繁琐
用redux小题大做
context提供了一种比较高级的组件传值的能力
import React from 'react'
// 创建 Context 填入默认值(任何一个 js 变量)
const ThemeContext = React.createContext('light')
// 底层组件 - 函数式组件
function ThemeLink (props: any) {
// const theme = this.context // 会报错。函数式组件没有实例,即没有 this
// 函数式组件可以使用 Consumer
return <ThemeContext.Consumer>
{ value => <p>link's theme is {value}</p> }
</ThemeContext.Consumer>
}
// 底层组件 - class 组件
class ThemedButton extends React.Component {
// 指定 contextType 读取当前的 theme context。
// static contextType = ThemeContext // 也可以用 ThemedButton.contextType = ThemeContext
render() {
const theme = this.context // React 会往上找到最近的 theme Provider,然后使用它的值。
return <div>
<p>button's theme is {theme}</p>
</div>
}
}
ThemedButton.contextType = ThemeContext // 指定 contextType 读取当前的 theme context。
// 中间的组件再也不必指明往下传递 theme 了。
function Toolbar(props: any) {
return (
<div>
<ThemedButton />
<ThemeLink />
</div>
)
}
class App extends React.Component<{}, {
theme?: string
}> {
constructor(props:any) {
super(props)
this.state = {
theme: 'light'
}
}
render() {
return <ThemeContext.Provider value ={this.state.theme as string}>
<Toolbar />
<hr/>
<button onClick={this.changeTheme}>change theme</button>
</ThemeContext.Provider>
}
changeTheme = () => {
this.setState({
theme: this.state.theme === 'light' ? 'dark' : 'light'
})
}
}
export default App
运行结果:
UseContext的使用
代码案例:
import React, { useContext } from "react";
const themes = {
light: {
foreground: '#000',
background: '#eee',
},
dark: {
foreground: '#fff',
background: '#222'
}
}
// 创建 Context
const ThemeContext = React.createContext(themes.light)
// 隔层传递
function ThemeButton(){
const theme = useContext(ThemeContext)
return <button style = {{background: theme.background, color: theme.foreground}}>
hello world
</button>
}
function Toolbar(){
return <div>
<ThemeButton></ThemeButton>
</div>
}
function App(){
return <ThemeContext.Provider value = {themes.dark}>
<Toolbar></Toolbar>
</ThemeContext.Provider>
}
export default App
代码案例:
import React, { useState, useContext } from 'react';
import './App.css';
import UseContextOne from './components/useContext'
interface IThemeProps {
[key: string] : {color: string; background: string;}
}
const themes: IThemeProps = {
'light': {
color:'#000',
background: '#eee'
},
'dark': {
color:'#fff',
background: '#222'
}
}
export const ThemeContextOne = React.createContext(themes.light)
function App() {
return (
<div className="App">
<ThemeContextOne.Provider value = {themes.light}>
<UseContextOne />
</ThemeContextOne.Provider>
</div>
);
}
export default App;
useContext.tsx
import React, {useContext} from 'react'
import {ThemeContextOne} from "../App"
export default function Context() {
const theme = useContext(ThemeContextOne)
console.log(theme)
const style = {
background: theme.background,
color: theme.color
}
return (
<div>
<button style = {style}>button</button>
</div>
)
}