Функция вызывается несколько раз в функциональном компоненте React - PullRequest
0 голосов
/ 23 апреля 2020

Ниже приведен файл компонента SinglePostBySearch. js

import React, { useState } from 'react'
import Post from './Post'
const axios = require('axios')

const getElt=({loading},{isThereQuery},{posts})=>{
    console.log(posts)
    if(!loading && isThereQuery)
    {
        return(
            <Post post={posts} id={posts.id} /> 
        )
    }
    if(loading)
    {
        return <div>Loading</div>
    }
    if(!(loading && posts))
    {
        return <div>No post from the user</div>
    }
}

function SinglePostBySearch(props) {
    const [posts, setPosts] = useState({})
    const [isThereQuery,setIsThereQuery]=useState(false)
    const [loading,setIsLoading]=useState(false)
    const fetchPost = (event) => {
        const postId = event.target.value
        if (postId) {
            setIsThereQuery(false)
            setIsLoading(true)
            axios.get(`https://jsonplaceholder.typicode.com/posts/${postId}`).then(res => {
                setPosts(res.data)
                setIsThereQuery(true)
                setIsLoading(false)
            }).catch(err => {
                console.log(err)
                setIsLoading(false)
                setPosts({})
            })
        }
        else{
            setPosts({})
            setIsThereQuery(false)
        }

    }
    return (
        <div>
            Hello {props.username}, enter a <strong>userId</strong> below
            <input type="text" onChange={fetchPost} />
            {getElt({loading},{isThereQuery},{posts})}
        </div>
    )
}
export default SinglePostBySearch

Проблема / вопрос : в возвращении функционального компонента в третьей строке I звоню другой функции getElt . Кажется, он вызывается примерно 4 или 5 раз, что я понял из console.log, который я вставил в первую строку функции getElt . Я хотел бы знать, почему он вызывается так много раз, когда он должен вызываться только один раз.

Я хотел бы отметить, что у меня нет дочерних операторов журнала в дочернем компоненте Post , который возвращается функцией getElt

Ответы [ 2 ]

0 голосов
/ 23 апреля 2020

Это заблуждение в React сегодня. Многие думают, что компонент функции не будет вызван, если реквизит и состояние не изменятся. По правде говоря, ваша функция может вызываться много раз при повторном рендеринге родительского компонента, и React проверяет старый Shadow DOM, чтобы определить, соответствует ли он новому Shadow DOM. Что мы можем скажем, так это то, что возвращенный JSX не будет обновляться в реальном DOM, если реквизиты и состояние не были изменены.

Что вы можете сделать, чтобы сократить время Движок React вызывает компонент функции, это попытка предотвратить ненужное обновление компонентов (включая ваши родительские компоненты). Вот несколько вещей, которые я вижу, глядя на ваш код:

  1. Новый экземпляр fetchPost создается при каждом вызове вашей функции. Это означает, что при каждом выполнении у него будет другой адрес памяти. Затем он передается дочерним компонентам как props, что означает, что каждый раз, когда выполняется ваш SinglePostBySearch компонент, дочерние элементы будут вынуждены отображаться. У вас могут быть похожие ситуации в родительском компоненте, которые вызывают чрезмерный вызов этого компонента. Чтобы избежать этого, любая функция, которую вы передаете children как prop, должна быть заключена в useCallback, чтобы она правильно запоминалась и не создавала новый экземпляр каждый раз.

  2. Вы вызываете функцию getElt каждый раз, когда выполняется функция компонента, даже если данные не изменились. Если вам необходимо предотвратить многократное выполнение функции, это может быть полезно для useMemo или useCallback (в зависимости от варианта использования) и указания зависимостей (loading, isThereQuery, posts) в массиве deps крючка. Таким образом, функция будет пересчитана только при изменении любой из этих зависимостей.

  3. Вы заключаете loading, isThereQuery и posts в анонимный объект {} каждый раз, когда вы передаете их. Это создает новый объект каждый раз, когда он видит это, что означает, что у него есть новый адрес памяти - и заставит всех потомков, которым вы передадите его в качестве реквизита, перерисовать. Хук useState уже поддерживает адрес памяти значения, поэтому, обернув его в новый объект, вы можете потенциально вызвать проблемы.

В React, когда вы используете интерполяцию для привязки данные непосредственно в JSX ({getElt({loading},{isThereQuery},{posts})}), React считает это дочерним элементом. Я не уверен, как анонимный объект повлияет на это, но не мешает избавиться от лишних объектов, обертывающих каждый параметр, тем более, что вы все равно снова разрушаете их в функции getElt.

0 голосов
/ 23 апреля 2020

Он отображается так много раз, потому что переменные, которые вы передаете {loading},{isThereQuery},{posts}, меняются столько раз. Если вы хотите ограничить количество вызовов, вы можете закорочить одно из значений, например, loading && getElt({loading},{isThereQuery},{posts}).

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