На этот раз я полностью получаю использование useReducer - useContext

React.js
На этот раз я полностью получаю использование useReducer - useContext

useReducer-Основные понятия

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 по сравнению с функциями обратного вызова:

  1. По сравнению с настраиваемым именем функции обратного вызова API контекста более понятно, и мы можем более четко знать, какие компоненты используют диспетчеризацию, поток данных и изменения в приложении. Это также является преимуществом однонаправленного потока данных React.

  2. Лучшая производительность: если функция обратного вызова передается в качестве параметра, поскольку функция рендеринга будет меняться каждый раз, это также приведет к рендерингу дочернего компонента. Конечно, мы можем использоватьuseCallback решает эту проблему, но по сравнению сuseCallbackReact официально рекомендует использовать 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, все статьи также будут обновляться синхронно сЗнай колонкуа такжеСчет наггетс, мы еженедельно делимся несколькими высококачественными техническими статьями о внешнем интерфейсе. Если вам понравилась эта статья, я надеюсь, что вы можете поставить палец вверх.

использованная литература