useReducer-использовать статьи
useReducer — используется с useContext
Добро пожаловать в третью часть нашей серии useReducer.Если вы впервые видите эту серию, я рекомендую прочитать первые две:
Использование useReducer упоминалось в конце прошлой статьи, что может помочь нам централизованно справляться со сложным управлением состоянием. Но если наша страница очень сложная и разделена на несколько слоев и компонентов, как мы можем инициировать эти изменения состояния в подкомпонентах, например, инициировать операцию ошибки входа в систему в LoginButton?
В этой статье будет показано, как использовать другой высокоуровневый Hook-useContext для решения этих проблем.
useContext
Как видно из названия, он использует React Context наподобие Hook. Краткое введениеContext
Понятие и использование , дополнительные сведения о контексте могут относиться кофициальная документация.
введение контекста
Следующее определение взято из официальной документации:
Context is designed to share data that can be considered “global” for a tree of React components, such as the current authenticated user, theme, or preferred language.
Проще говоряContext
Его роль заключается в предоставлении технологии глобального общего доступа к содержащемуся в нем дереву компонентов.
// 第一步:创建需要共享的context
const ThemeContext = React.createContext('light');
class App extends React.Component {
render() {
// 第二步:使用 Provider 提供 ThemeContext 的值,Provider所包含的子树都可以直接访问ThemeContext的值
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
}
// Toolbar 组件并不需要透传 ThemeContext
function Toolbar(props) {
return (
<div>
<ThemedButton />
</div>
);
}
function ThemedButton(props) {
// 第三步:使用共享 Context
const theme = useContext('ThemeContext');
render() {
return <Button theme={theme} />;
}
}
оContext
Еще один важный момент заключается в том, что при изменении значения Context Provider все его субпотребители будут отображаться.
вход в версию useContext
Прочитав приведенную выше демонстрацию, мы оглядываемся назад и думаем о том, как использоватьcontext
Чтобы решить проблему изменения состояния редуктора из компонентов класса-потомка, упомянутых в начале нашего вопроса. Правильно, функция отправки используется как значение контекста и используется совместно с дочерними компонентами страницы.
// 定义初始化值
const initState = {
name: '',
pwd: '',
isLoading: false,
error: '',
isLoggedIn: false,
}
// 定义state[业务]处理逻辑 reducer函数
function loginReducer(state, action) {
switch(action.type) {
case 'login':
return {
...state,
isLoading: true,
error: '',
}
case 'success':
return {
...state,
isLoggedIn: true,
isLoading: false,
}
case 'error':
return {
...state,
error: action.payload.error,
name: '',
pwd: '',
isLoading: false,
}
default:
return state;
}
}
// 定义 context函数
const LoginContext = React.createContext();
function LoginPage() {
const [state, dispatch] = useReducer(loginReducer, initState);
const { name, pwd, isLoading, error, isLoggedIn } = state;
const login = (event) => {
event.preventDefault();
dispatch({ type: 'login' });
login({ name, pwd })
.then(() => {
dispatch({ type: 'success' });
})
.catch((error) => {
dispatch({
type: 'error'
payload: { error: error.message }
});
});
}
// 利用 context 共享dispatch
return (
<LoginContext.Provider value={dispatch}>
<...>
<LoginButton />
</LoginContext.Provider>
)
}
function LoginButton() {
// 子组件中直接通过context拿到dispatch,出发reducer操作state
const dispatch = useContext(LoginContext);
const click = () => {
if (error) {
// 子组件可以直接 dispatch action
dispatch({
type: 'error'
payload: { error: error.message }
});
}
}
}
Видно, что в useReducer в сочетании с useContext функция диспетчеризации предоставляется всем компонентам в дереве компонентов через контекст. , вместо того, чтобы передавать его слой за слоем, добавляя функции обратного вызова через свойства.
Преимущества использования Context по сравнению с функциями обратного вызова:
-
По сравнению с настраиваемым именем функции обратного вызова API контекста более понятно, и мы можем более четко знать, какие компоненты используют диспетчеризацию, поток данных и изменения в приложении. Это также является преимуществом однонаправленного потока данных React.
-
Лучшая производительность: если функция обратного вызова передается в качестве параметра, поскольку функция рендеринга будет меняться каждый раз, это также приведет к рендерингу дочернего компонента. Конечно, мы можем использоватьuseCallback решает эту проблему, но по сравнению с
useCallback
React официально рекомендует использовать useReducer, потому что React гарантирует, что диспетчеризация всегда останется неизменной и не вызовет повторного рендеринга потребительского компонента.
Для получения дополнительной информации, пожалуйста, обратитесь к официальному FQA:
how-to-avoid-passing-callbacks-down
how-to-read-an-often-changing-value-from-usecallback
Суммировать
Пока пользуйтесь трехчастной серией Reducer на всем протяжении, кратко напомним:
- если ваша страница
state
Очень просто, можно использовать напрямуюuseState
- если ваша страница
state
Более сложный (состояние является объектом или много состояний разбросано повсюду), пожалуйста, используйте userReducer - Если иерархия компонентов вашей страницы глубокая и вам нужны дочерние компоненты для запуска
state
Для изменений рассмотрите useReducer + useContext
Последняя практика, приветствуем всех, чтобы отметить нашуБлог фронтенд-команды Renrendai, все статьи также будут обновляться синхронно сЗнай колонкуа такжеСчет наггетс, мы еженедельно делимся несколькими высококачественными техническими статьями о внешнем интерфейсе. Если вам понравилась эта статья, я надеюсь, что вы можете поставить палец вверх.