Будет ли ReactDOM.hydrate() запускать методы жизненного цикла на клиенте?
Из Реакции 16 документов о ReactDOM.hydrate()
,
То же, что и render(), но используется для увлажнения контейнера, содержимое HTML которого было обработано ReactDOMServer. React попытается присоединить прослушиватели событий к существующей разметке.
Будет
ReactDOM.hydrate()
также запустить методы жизненного цикла на клиенте, такие какcomponentWillMount()
,componentDidMount()
во время первоначального рендеринга?Будет
render()
метод будет вызываться на клиенте во время гидратации? Я полагаю, нет, потому что это разница междуReactDOM.render()
а такжеReactDOM.hydrate()
?
Если render
метод не будет вызываться на клиенте, мы не ожидаем componentDidMount()
метод жизненного цикла для запуска.
Если ни один из методов жизненного цикла не вызывается на клиенте, как мы узнаем, когда React завершил рендеринг. Я полагаю callback
в следующем синтаксисе:
ReactDOM.hydrate (элемент, контейнер [, обратный вызов])
Я хочу понять, есть ли методы / ловушки жизненного цикла (которые дают больший контроль над приложением), доступные, когда React "пытается присоединить прослушиватели событий к существующей разметке".
3 ответа
Поскольку ReactDOM.hydrate вызывается (и должен вызываться) на клиенте, тогда YES должен запускать componentDidMount. componentWillMount уже вызывается при визуализации на сервере.componentDidMount не запускается на сервере, поэтому, когда вы вызываете гидрат, приложение запускает событие.
Думайте о гидрате как о другом методе рендеринга. Это делает, но не так. Он ищет несоответствия между вашим сервером рендеринга React и вашим клиентом React. Это не делает все снова.
React ожидает, что отображаемый контент идентичен между сервером и клиентом. Он может исправлять различия в текстовом содержимом (например, временные метки), но вы должны рассматривать несоответствия как ошибки и исправлять их
Однако вы можете захотеть сделать что-нибудь сумасшедшее, например, рендеринг чего-то совершенно другого на стороне клиента (чем то, что рендерилось на сервере). Для этого обратите внимание на этот абзац
Если вам преднамеренно нужно визуализировать что-то другое на сервере и клиенте, вы можете выполнить двухпроходный рендеринг. Компоненты, которые отображают что-то другое на клиенте, могут читать переменную состояния, такую как this.state.isClient, для которой вы можете установить значение true в componentDidMount(). Таким образом, начальный этап рендеринга будет отображать тот же контент, что и сервер, избегая несовпадений, но дополнительный этап будет происходить синхронно сразу после гидратации. Обратите внимание, что этот подход замедлит ваши компоненты, потому что они должны визуализироваться дважды, поэтому используйте его с осторожностью.
Так что, как вы можете видеть, он делает проход. Если нет несоответствий, React оптимизируется для этого.
Надеюсь, это прояснилось. Я говорю из опыта React SSR и базового понимания чтения документации.
Отображаемые элементы, вероятно, не одинаковы между сервером и клиентом, потому что изначально элементы визуализируются в тексты на сервере в памяти, поэтому они не монтируются. Когда контент перемещается на клиент, его можно повторно подключить, чтобы отреагировать через
hydrate
что является поддельным «рендерингом» для связи с остальными функциями реагирования, такими как события.
Чтобы сказать, когда он гидратирован, вот отрывок из Интернета, в котором, как я нашел, четко указано вышеупомянутое. https://dev.to/merri/understanding-react-ssr-spa-hydration-1hcf?signin=true
const HydrateContext = createContext('hydrated')
export function useIsHydrated() {
return useContext(HydrateContext)
}
export function IsHydratedProvider({ children }) {
const [isHydrated, setIsHydrated] = useState(false)
useEffect(() => {
setIsHydrated(true)
}, [])
return (
<HydrateContext.Provider value={isHydrated}>
{children}
</HydrateContext.Provider>
)
}
Чтобы использовать это,
function MyComponent() {
const isHydrated = useIsHydrated()
return !isHydrated ? 'Initial render' : 'SPA mode'
}
function App() {
return (
<IsHydratedProvider>
<MyComponent />
</IsHydratedProvider>
)
}
Мне кажется, любой визуализированный компонент телепортируется с сервера на клиента.
ps Вот еще одна статья, в которой рассказывается о втором рендере после монтирования, https://medium.com/swlh/how-to-use-useeffect-on-server-side-654932c51b13
Я читал тип
ReactDOM.hydrate
в системе TypeScript:
(
element: SFCElement<any> | Array<SFCElement<any>>,
container: Container| null,
callback?: () => void
): void;
И пример к приведенному выше объявлению:
ReactDOM.hydrate(
<App />, // element
document.getElementById('root'), // container
() => { // callback
/* do what you want after hydration */
}
);