Первый взгляд на React Hooks и преобразование SSR

React.js

Hooks

React v16.8опубликованоHooks, который в основном решает проблему управления состоянием кросс-компонентного и повторного использования компонентов.

существуетclassСостояние компонентов инкапсулируется в объекты, а затем взаимодействие состояний между компонентами организуется через односторонний поток данных. В этом режиме управление состоянием между компонентами становится очень сложным, а повторно используемые компоненты также будут иметь много побочных эффектов, поскольку они совместимы с разными компонентами.

Позже былоReduxБиблиотека управления состоянием, такая как эта, для унифицированного управления состоянием компонентов. Но это многослойность по-прежнему делает код очень сложным, требуя большего количества вложений, состояний и методов и часто переключаясь между несколькими файлами при написании кода.hooksЭто решение вышеуказанных проблем.

Статья неhooksСлишком много подробных вводных, рекомендуется зайти на официальный сайт для общего понимания, прежде чем читать эту статью. Эта статья основана на предыдущей статье "Реализовать рендеринг ssr на стороне сервера"код, сделайhooksМодернизация. Код отправлен в репозиторийhooksВ ветке ссылка на репозиторийGitHub.com/letter-v/реагировать-….

Объектно-ориентированное программирование и функциональное программирование

в пониманииhooksВ процессе я постепенно почувствовал разницу между объектно-ориентированным и функциональным программированием.

существуетclassВ режиме методы состояния и свойства инкапсулированы в компоненты, и компоненты взаимодействуют друг с другом как полноценные объекты, а модификацию состояния нужно обрабатывать в setState внутри объекта.

а такжеhooksВ шаблоне все является функцией, т.hooks, можно разделить на множество мелких единиц, а затем объединить, единица, которая изменяет состояние, является единицей.setметод, этот метод можно использовать в любом другомhooksпоявиться и позвонить. class более объектно-ориентированное программирование, в то время какhooksЭто больше функциональное программирование.

Reactне удаляетclass, но ввестиhooksЭто позволяет разработчикам делать лучший выбор на основе сценариев. Они по-прежнему будут поддерживать свои итерации в будущем.

Разнообразие

использоватьhooksПосле этого первоначальная концепция жизненного цикла изменится. Например, мы определяемhooksИндекс компонента, когда компонент работает,Indexвызов функции один разrender, то наш первыйrenderэквивалентно оригиналуwillMount,а такжеuseEffectбудет первымrenderВыполнить позже. Официальная документация сайта также говорит, что вы можете поставитьuseEffectHooksрассматривается какcomponentDidMount,componentDidUpdateа такжеcomponentWillUnmountкомбинация.stateтакже былuseStateзаменять,useStateПередайте начальное значение и верните переменную и измените переменнуюsetметод.

Когда мы рендерим на стороне сервера, в прошлой статье говорилось, что жизненный цикл будет выполняться только до тех пор, покаwillMountпервый раз послеrender. что в насhooksВ режиме рендеринг на стороне сервера будет выполняться Index hooksпервый разrender,а такжеuseEffectвыполняться не будет.

function Index(props){
    console.log('render');
    const [desc, setDesc] = useState("惹不起");
    useEffect(() => {
        console.log('effect')
    })
    return (<div>{desc}</div>)
}

useEffect

если используетсяuseEffect, компонент перехватывает каждый разrenderпосле,useEffectбудет казнен.useEffectПервый входной параметр — это метод, который нужно вызвать, метод может возвращать метод, и возвращаемый метод будет выполняться, когда это не первый раз.useEffectВызывается ранее, также вызывается при выгрузке компонента.

Второй параметр — передать массив, который используется для ограниченияuseEffectКоличество выполнений, если этот параметр не передан,useEffectкаждый разrenderпри исполнении. Если передается второй параметр массива, он не будет выполняться в первый раз.useEffect, переменные в массиве сравниваются с предыдущимrenderЕсли есть изменение, оно будет запущено сноваuseEffectвоплощать в жизнь.

Посмотрите на следующий код, когда страница перваяrender,useEffectВыполнить асинхронный сбор данных, если сбор данных прошел успешно,setListПосле установки значения (что-то вродеsetStateвызоветrender), снова выполнитсяrender,а такжеuseEffectОн будет выполнен снова.После завершения запроса данных,setListприведет кrender, таким образом попадая в бесконечный цикл.

const [list, setList] = useState([]);
useEffect(() => {
    API.getData().then(data=>{
        if (data) {
            setList(data.list);
        }
    });
});

Поэтому вам нужно использовать второй параметр, чтобы ограничить количество выполнений, мы передаем в1, это может быть реализовано только один разuseEffect. Конечно, вы также можете пройти вuseStateПеременная.

const [list, setList] = useState([]);
useEffect(() => {
    API.getData().then(data=>{
        if (data) {
            setList(data.list);
        }
    });
}, [1]);

трансформация класса

В помещении оригинального склада SSR, только для составной части, выполнитеhooksМодернизация. Сначала просмотритеgetInitialPropsсуществуетclassрежим, находится вclassНапишиstaticстатический метод следующим образом:

export default class Index extends Base {
  static async getInitialProps() {
    let data;
    const res = await request.get("/api/getData");
    if (!res.errCode) data = res.data;
    return {
      data
    };
  }
}

существуетhooksсередина,classстановится обычной функцией, предыдущее наследство становится ненужным и не может адаптироваться к потребностям, поэтомуgetInitialPropsНапрямую прописанный в свойствах функции формат данных, возвращаемый самим методом, остается неизменным, а возвращается объект. следующим образом:

function Index(props) {
}
Index.getInitialProps = async () => {
  let data;
  const res = await request.get("/api/getData");
  if (!res.errCode) data = res.data;
  return {
    data
  };
};

Включить определенные страницыtitle, который также использовался ранееstatic, а теперь и мыIndex.title = 'index' Это определено.

hooksТребования к спецификации следующие со ссылкой на китайскийReactДокументация:

  • Хуки можно вызывать только на верхнем уровне. Не вызывайте хуки в циклах, потоке управления и вложенных функциях.
  • Хуки можно вызывать только из функциональных компонентов React. Не вызывайте хуки в обычных функциях JavaScript. (Кроме того, вы можете вызывать хуки в своих пользовательских хуках.)

существуетclassрежим, мы наследуемBase,BaseОпределяетconstructorа такжеcomponentWillMountиметь дело сstateа такжеprops, что может помочь нам решить задачу назначения и получения данных состояния инициализации при рендеринге на стороне сервера и рендеринге на стороне клиента, чтобы мы могли унифицировать набор кода для запуска на клиенте и сервере (при необходимости см. предыдущую статью для получения подробной информации). ).

classНаследование в шаблонахBaseОн относится к модели объектно-ориентированного программирования, в то время какhooksВ режиме, в связи с необходимостью использования внутри функцииuseStateЧтобы определить состояние и вернуть методы для установки состояния, кажется более функциональным программирование, в этом сценарии наследование становится непригодным. Поэтому необходимоBaseпеределывать, вBaseзаписыватьhooks, в компоненте страницыhooksиспользуется в.

существуетclassрежим, мы используем наследованиеBaseиметь дело сstateа такжеprops,из-заBaseуже упакованоconstructorа такжеcomponentWillMountиметь дело сstateа такжеprops, поэтому нам нужно только определить статическийstateа такжеgetInitialProps, компонент автоматически обработает соответствующую логику, и примерно используемый код выглядит следующим образом.

export default class Index extends Base {
  static state = {
    desc: "Hello world~"
  };
  static async getInitialProps() {
    let data;
    const res = await request.get("/api/getData");
    if (!res.errCode) data = res.data;
    return {
      data
    };
  }
}

существуетhooksРежим другой, т.к. от наследования отказались, нужно использоватьBaseнастроитьhooks, а затем используйте его в компоненте страницы.BaseсерединаgetPropsа такжеrequestInitialDataКогда вызывается хук, вам нужно передать текущийIndexобъект компонента, затем в Base hooks вернуть начальное значение переменной вsetизменить текущийhooksЗначения состояния в , примерно используются следующим образом:

import { getProps, requestInitialData } from "../base";

function Index(props) {
  const [desc, setDesc] = useState("Hello world~");
  //getProps获取props中的ssrData,重构和服务端渲染时props有值,第三个参数为默认值
  const [data, setData] = useState(getProps(props, "data", ""));

  //在单页面路由页面跳转,渲染组件时,requestInitialData调用getInitialProps
  requestInitialData(props, Index, { data: setData });
  return (<div>{data}</div>)
}
Index.getInitialProps = async () => {
  let data;
  const res = await request.get("/api/getData");
  if (!res.errCode) data = res.data;
  return {
    data
  };
};
export default Index;

После инкапсуляции таким образом мы по-прежнему гарантируем, что набор кода может работать на сервере и клиенте,requestInitialDataТретий входящий параметр метода — это объект, который переходит в состояние, которое необходимо изменить.setметод, наконецgetInitialPropsПосле возврата данных они будут сравниваться с пришедшим объектом, и имя атрибута будет называтьсяsetметод изменения состояния,requestInitialDataЯвляетсяuseEffect hook, код показывает, как показано ниже


export function requestInitialData(props, component, setFunctions) {
  useEffect(() => {
    //客户端运行时
    if (typeof window != "undefined") {
      //非同构时,并且getInitialProps存在
      if (!props.ssrData && component.getInitialProps) {
        component.getInitialProps().then(data => {
          if (data) {
            //遍历结果,执行set赋值
            for (let key in setFunctions) {
              for (let dataKey in data) {
                if (key == dataKey) {
                  setFunctions[key](data[dataKey]);
                  break;
                }
              }
            }
          }
        });
      }
    }
  },[1]);
}

Пока что для моего предыдущего кода SSR это сделаноhooksтрансформация.React hooks Трансформация очень плавная,classа такжеhooksСмешивание не вызовет никаких проблем, если вам нужно использовать его в старом проекте.hooksили к оригиналуclassДля преобразования вполне возможно медленно повторять часть за частью. КонечноReact Hooks а такжеuseContext  useReducerПодожди, почему бы тебе не попробовать Крючки прямо сейчас?

Статьи по Теме: "Реализовать рендеринг ssr на стороне сервера

Связанный склад:GitHub.com/letter-v/реагировать-…


Обратите внимание на публичный аккаунт великого поэта и получайте свежие статьи в первый раз.