Как реагирующий маршрутизатор предотвращает размонтирование компонентов при изменении маршрута? - PullRequest
1 голос
/ 01 августа 2020

Я начну с того, что скажу, что все работает правильно, просто я пытаюсь понять, что именно происходит и почему я наблюдаю такое поведение.

Допустим, у меня есть компонент, FooComponent и два разных маршрута: /foo и /bar. Я визуализирую их следующим образом:

<Route
    exact
    path="/foo"
    render={({ location }) => <FooComponent location={location} />}
/>
<Route
    path="/bar"
    render={({ location }) => <FooComponent location={location} />}
/>

При нажатии между страницами /foo и /bar кажется, что FooComponent монтируется только один раз. Чтобы проверить это, вот как реализован FooComponent:

const FooComponent = ({ location }) => {
  useEffect(() => {
    console.log("Mount");
    return () => {
      console.log("Cleanup");
    };
  }, []);
  return <div>At {location.pathname}</div>;
};

Mount регистрируется только один раз.

Это меня полностью озадачивает, поскольку FooComponent отображается двумя совершенно разными родительских Route компонентов, и я думал, что React будет выполнять согласование только при повторном рендеринге одного и того же родительского компонента с разными дочерними элементами. Более того, изменение одного значения на возврат <div><FooComponent location={location} /></div> и оставление другого как есть приведет к отключению компонента.

Здесь - воспроизводимый пример.

1 Ответ

0 голосов
/ 01 августа 2020

Как и то, что вы упомянули, я считаю, что это поведение в основном связано с процессом React Reconciliation. Всякий раз, когда элементы root имеют разные типы, в нашем случае <div /> против <FooComponent />, React создаст новое дерево. Вот почему мы наблюдаем событие размонтирования.

В следующем случае опора (местоположение) для FooComponent будет изменена, когда мы go выберем другой маршрут. Поскольку у нас есть два элемента React DOM одного и того же типа, React будет только обновлять и повторно отображать компонент.

// location is changed by react-route
<Route
    exact
    path="/foo"
    render={({ location }) => <FooComponent location={location} />}
/>
<Route
    path="/bar"
    render={({ location }) => <FooComponent location={location} />}
/>


const FooComponent = ({ location }) => {
  useEffect(() => {
    console.log("Mount");
    return () => {
      console.log("Cleanup");
    };
  }, []);
  
  // the parent components is the same, only the child node of the following div is chnaged, so React rerenders the div.
  return <div>At {location.pathname}</div>;
};

На стороне реактивного маршрутизатора Route не меняет структуру DOM, если вы посмотрите исходный код. он действует только как поставщик контекста.

return (
            <RouterContext.Provider value={props}>
              {props.match
                ? children
                  ? typeof children === "function"
                    ? __DEV__
                      ? evalChildrenDev(children, props, this.props.path)
                      : children(props)
                    : children
                  : component
                  ? React.createElement(component, props)
                  : render
                  ? render(props)
                  : null
                : typeof children === "function"
                ? __DEV__
                  ? evalChildrenDev(children, props, this.props.path)
                  : children(props)
                : null}
            </RouterContext.Provider>
          );

Ссылки:

react-dom / Router. js

React / Выверка

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...