Правильно ли не включать зависимость от цели на useEffect, чтобы избежать повторного рендеринга при использовании реакции-маршрута? - PullRequest
0 голосов
/ 04 мая 2020

В моем случае здесь я хочу избежать повторного рендеринга компонента <Checkout/> после замены URL-адреса props.history.replace(props.match.path + '/contact-data' для загрузки component <ContactData/>.

. Как видно на useEffect когда <Checkout/> загружается, он получает query хвост на url, что-то вроде этого: http://localhost:3000/checkout?cheese=0&salad=0&special=0&veggie=1. Затем я перенаправляю на URL, который выглядит следующим образом: http://localhost:3000/checkout/contact-data, который отображает <ContactData/> ниже, с обоими <Checkout/> & <ContactData/> на экране.

Мой вопрос касается useEffect. Если я добавлю props.location.search в качестве зависимости useEffect, useEffect вызовет повторный рендеринг <Checkout/>, действуя как ComponentDidUpdate каждый раз, когда props.location.search изменяется.

В этом случае использования, когда я заменяю url для загрузки <ContactData/>, props.location.search изменится и <Checkout/> выполнит повторную визуализацию, если у меня будет добавлена ​​зависимость, как описано выше.

Теперь я решил эту проблему, не добавляя зависимость к useEffect и оставляя array из deps пустым, заставляя useEffect запускаться только один раз. Это плохая практика? Будет ли правильный способ сделать это без обмана useEffect?

useEffect(() => {
        const query = new URLSearchParams(props.location.search)
        const ingredients = {};
        for (let param of query.entries()) {
            ingredients[param[0]] = +param[1]
        }
            setNewOrder(ingredients)
    },[props.location.search])

Даже используя useEffect с пустым array из dependencies Я заметил, что <Checkout/> все еще рендерит, но, конечно, не запускает код внутри useEffect в этом новом цикле render

Можно ли реально избежать <Checkout/> повторного рендеринга здесь?

import React, {useEffect, useState, Fragment, Suspense} from 'react'
import {withRouter, Route} from "react-router-dom";
import CheckoutSummary from "../../components/CheckoutSummary/CheckoutSummary";
const ContactData = React.lazy(() => import("./ContactData/ContactData"))

function Checkout(props) {
    const [newOrder, setNewOrder] = useState(null);
    const returnToOrderCreationHandler = () => {
        props.history.goBack()
    }

    const confirmOrderHandler = () => {
        props.history.replace(props.match.path + '/contact-data')
    }
    useEffect(() => {
        const query = new URLSearchParams(props.location.search)
        const ingredients = {};
        for (let param of query.entries()) {
            ingredients[param[0]] = +param[1]
        }
            setNewOrder(ingredients)
    },[])
    return (
        <Fragment>
            <CheckoutSummary ingredients={newOrder}
                             cancelCheckout={returnToOrderCreationHandler}
                             confirmCheckout={confirmOrderHandler}/>
            <Route path={props.match.path +  '/contact-data'} render={() =>
                <Suspense fallback={<h1>Loading...</h1>}><ContactData/></Suspense>}/>
        </Fragment>
    )
}

export default withRouter(Checkout)

1 Ответ

0 голосов
/ 04 мая 2020

Является ли решение ниже хака или хорошей практикой в ​​этом случае? Учитывая идею, стоящую за кодом, в отношении желаемого поведения приложений. Или я могу оставить массив зависимостей пустым в useEffect, поскольку не хочу, чтобы он повторно отображался, а затем игнорировать ошибку eslint?

 useEffect(() => {
        if(props.location.search.length > 0) {
            const query = new URLSearchParams(props.location.search)
            const ingredients = {};
            for (let param of query.entries()) {
                ingredients[param[0]] = +param[1]
            }
            setNewOrder(ingredients)
        }
    },[props.location.search])

<Checkout/> цикл:

  • 1-й рендер - newOrder инициализируется как null

  • 2-й рендеринг - useEffect выполняется - newOrder устанавливается на то, что получено до props.location.search

  • 3-й визуализации - после выполнения function confirmOrderHandler изменения url props.match.path + '/contact-data'. useEffect распознает изменение по его зависимости props.location.search, но перед повторным выполнением кода в своем блоке он проверяет, есть ли еще string в props.location.search, что в этом случае не будет истинным, как мы имеем заменил url, поэтому логика c не выполняется повторно и state сохраняется.

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