一、先了解下 useContext 写法
index.tsx
import { useState, useContext } from 'react';
import { themes, ThemeContext } from './context';
const ContextDemo = () => {
const [style, setStyle] = useState('light');
const onChangeTheme = () => {
setStyle(style === 'light' ? 'dark' : 'light');
};
return (
<ThemeContext.Provider value={{ theme: themes[style], onChangeTheme }}>
<Toolbar />
</ThemeContext.Provider>
);
};
function Toolbar(props) {
const { onChangeTheme } = useContext(ThemeContext);
return (
<div>
<ThemedButton />
<button onClick={onChangeTheme}>change</button>
</div>
);
}
function ThemedButton() {
const { theme } = useContext(ThemeContext);
console.log(theme, 'theme');
return (
<button style={{ background: theme.background, color: theme.foreground }}>
I am styled by theme context!
</button>
);
}
export default ContextDemo;
context.ts
import { createContext } from 'react';
export const themes = {
light: {
foreground: '#000000',
background: '#eeeeee',
},
dark: {
foreground: '#ffffff',
background: '#222222',
},
};
export const ThemeContext = createContext(null);
二、 结合 useReducer
index.tsx
import { useReducer, useContext } from 'react';
import { themes, ThemeContext, demoReducer } from './context';
const ContextDemo = () => {
const [demoReducerData, dispatch] = useReducer(demoReducer, {
theme: themes.light,
});
const { theme } = demoReducerData;
return (
<ThemeContext.Provider value={{ theme: theme, dispatch }}>
<Toolbar />
</ThemeContext.Provider>
);
};
function Toolbar(props) {
const { dispatch } = useContext(ThemeContext);
return (
<div>
<ThemedButton />
<button
onClick={() => {
dispatch({ type: 'dark' });
}}
>
change dark
</button>
</div>
);
}
function ThemedButton() {
const { theme } = useContext(ThemeContext);
console.log(theme, 'theme');
return (
<button style={{ background: theme.background, color: theme.foreground }}>
I am styled by theme context!
</button>
);
}
export default ContextDemo;
context.ts
import { createContext } from 'react';
export const themes = {
light: {
foreground: '#000000',
background: '#eeeeee',
},
dark: {
foreground: '#ffffff',
background: '#222222',
},
};
export const demoReducer = (state, action) => {
switch (action.type) {
case 'light':
return {
...state,
theme: themes.light,
};
case 'dark':
return {
...state,
theme: themes.dark,
};
default:
throw new Error();
}
};
export const ThemeContext = createContext(null);
三、最后
- 如果页面
state很简单,可以直接使用useState; - 如果页面
state比较复杂(state是一个对象或者state非常多散落在各处)请使用userReducer; - 如果页面组件层级比较深,并且需要子组件触发
state的变化,可以考虑useReducer+useContext;