[英]Function being called multiple times in React functional component
下面是组件文件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
问题/问题:在功能组件的返回中,在第三行中,我正在调用另一个 function getElt 。 它似乎被调用了大约 4 或 5 次,这是我从我插入getElt function 的第一行的 console.log 中得出的。 我想知道为什么它被调用了这么多次,而它应该只调用一次。
我想指出,function getElt返回的子组件Post中没有任何控制台日志语句
这是当今 React 中的一个误解。 许多人认为如果 props 和 state 不变,则不会调用 function 组件。 事实上,当父组件重新渲染时,您的 function 可能会被多次调用,React 会检查旧的 Shadow DOM 以查看它是否与新的 Shadow DOM 匹配。 我们可以说,如果 props 和 state 没有改变,返回的 JSX 不会在真实的 DOM 中更新。
你可以做些什么来减少 React 引擎调用你 function 组件的次数,就是尽量避免你的组件进行不必要的更新(包括你的父组件)。 以下是我在查看您的代码时看到的几件事:
每次调用fetchPost
实例。 这意味着在每次执行时,它将具有不同的 memory 地址。 然后它作为props
传递给子组件,这意味着每次执行SinglePostBySearch
组件时,子组件将被强制渲染。 您的父组件中可能有类似的情况导致该组件被过度调用。 为避免这种情况,您作为prop
传递给children
的任何 function 都应包装在useCallback
中,以便正确记忆,并且不会每次都重新创建新实例。
每次执行组件 function 时,您都在调用getElt
function,即使数据没有更改。 如果您需要阻止 function 执行这么多次,那么使用useMemo
或useCallback
(取决于用例)并在钩子的deps
数组中指定依赖项( loading
、 isThereQuery
、 posts
)会很有用。 这样,function 将仅在修改任何这些依赖项时重新计算。
每次传递时,您都在匿名 object {}
中包装loading
、 isThereQuery
和posts
。 每次看到它时都会实例化一个新的 object,这意味着它有一个新的 memory 地址 - 并且会导致您将其作为道具传递给的任何孩子重新渲染。 useState
挂钩已经维护了值的 memory 地址,因此通过将其包装在新的 object 中,您可能会导致问题。
在 React 中,每当您使用插值直接在 JSX 中绑定数据时( {getElt({loading},{isThereQuery},{posts})}
),React 都认为这是一个子元素。 我不确定匿名的 object 将如何影响这一点,但摆脱包装每个参数的多余对象并没有什么坏处,特别是因为无论如何你在getElt
function 中再次解构它们。
它被渲染了很多次,因为您传递的变量{loading},{isThereQuery},{posts}
正在改变很多次。 如果你想限制它被调用的次数,你可以短路其中一个值,例如loading && getElt({loading},{isThereQuery},{posts})
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.