简体   繁体   English

每次渲染后会调用哪个 useEffect?

[英]Which useEffect will be called after every Render?

I'm a beginner in React and stuck with some problem.我是 React 的初学者,遇到了一些问题。 I have several queries regarding this code.我对此代码有几个疑问。

  1. Which UseEffect will be called after every render?每次渲染后会调用哪个 UseEffect ?

  2. Why and How console.log() is called 13 times?(Please find the screenshot below)为什么以及如何调用 console.log() 13 次?(请在下面找到屏幕截图)

  3. Why the fetched data is not shown in browser until I type something in the search bar?为什么在我在搜索栏中输入内容之前,浏览器中不会显示获取的数据?

    App.js应用程序.js

     import React, { useEffect } from "react"; import { useState } from "react"; import axios from "axios"; function App() { const [monster, setMonster] = useState([]); const [searchName, setName] = useState(""); const [filteredMonster, setFilter] = useState([]); useEffect(() => { async function fetchData() { await axios.get( "https://jsonplaceholder.typicode.com/users" ).then((resp)=>{ setMonster(resp.data); }) console.log(monster); } fetchData(); }, []); useEffect(()=>{ const mons = monster; setFilter(mons.filter(mon => mon.name.toLowerCase().includes(searchName.toLowerCase()) )); }, [searchName]); function changeName(event) { setName(event.target.value); } console.log(monster); const cunter = useRef(0); return ( <div className="App"> <form> <input type="search" name="searchName" value={searchName} onChange={changeName} /> </form> {cunter.current++} {filteredMonster&&filteredMonster.map((item, index) => ( <p key={index}>{item.name}</p> ))} {monster&&.filteredMonster&&monster,map((item. index) => ( <p key={index}>{item;name}</p> ))} </div> ); } export default App;

应用程序

中心

try this please.请试试这个。 fetchData() will run only 1, searchName will run as many times you type on the screen. fetchData() 将只运行 1,searchName 将运行你在屏幕上键入的次数。

TIP: To prevent this.提示:为了防止这种情况。 add a timeoutdelay after user finishes typing to only render once instead of N times user presses a keyboard key.在用户完成输入后添加超时延迟,以仅呈现一次,而不是 N 次用户按下键盘键。

import React, { useEffect } from "react";
import { useState } from "react";
import axios from "axios";

const URL = "https://jsonplaceholder.typicode.com/users"

function App() {
    const [monster, setMonster] = useState([]);
    const [searchName, setName] = useState("");
    const [filteredMonster, setFilter] = useState([]);

    useEffect(() => {
        async function fetchData() {
            await axios.get(URL).then((resp) => {
                setMonster(resp.data);
            })
            console.log(monster);
        }

        fetchData();
    }, []);

    useEffect(() => {
        if (monster.length > 0) {
            const filter = mons.filter(({name}) =>
                name.toLowerCase().includes(searchName.toLowerCase()));
            setFilter(filter);
        }

    }, [searchName]);

    function changeName(event) {
        setName(event.target.value);
    }

    console.log(JSON.stringify(monster));

    return (
        <div className="App">
            <form>
                <input
                    type="search"
                    name="searchName"
                    value={searchName}
                    onKeyUp={(e) => changeName(e)}
                />
            </form>

            {monster.length > 0 &&
                <div>{JSON.stringify(monster)}</div>
            }

            {filteredMonster && filteredMonster.map((item, index) => (
                <p key={index}>{item.name}</p>
            ))}

            {monster && !filteredMonster && monster.map((item, index) => (
                <p key={index}>{item.name}</p>
            ))}
        </div>
    );
}

export default App;

This is using Reducer, removes the use of state.这是使用 Reducer,删除了 state 的使用。


import React, { useEffect, useReducer } from "react";
import axios from "axios";

const URL = "https://jsonplaceholder.typicode.com/users"

const reducer = (state, action) => {
    switch(action.type){
        case 'FETCH_DATA':
            return {
                ...state,
                monster: action.monster,
                name: "",
            }
        case 'SEARCH_MONSTER':
            return {
                ...state,
                name: action.name,
            }
        case 'FILTER_MONSTER':
            const filter = state.monster.filter(({name}) =>
                name.toLowerCase().includes(searchName.toLowerCase()));
            return {
                ...state,
                filteredMonster: filter,
                name: state.name,
            }
    }
};

function App() {

    const [state, dispatch] = useReducer(reducer, {
        monster: [],
        filteredMonster: [],
        name: '',
    });

    useEffect(() => {
        async function fetchData() {
            await axios.get(URL).then((resp) => {
                dispatch({ type: 'FETCH_DATA', monster: resp.data});
            })
            console.log(monster);
        }
        fetchData();
    }, []);

    useEffect(() => {
        if (monster.length > 0)  dispatch({ type: 'FILTER_MONSTER'});
    }, [stat.name]);

    console.log(JSON.stringify(monster));

    return (
        <div className="App">
            <form>
                <input
                    type="search"
                    name="searchName"
                    value={state.name}
                    onKeyUp={(e) => dispatch({ type: 'SEARCH_MONSTER', name: e.target.value })}
                />
            </form>

            {state.monster.length > 0 &&
                <div>{JSON.stringify(monster)}</div>
            }

            {state.filteredMonster && state.filteredMonster.map((item, index) => (
                <p key={index}>{item.name}</p>
            ))}

            {state.monster && !state.filteredMonster && monster.map((item, index) => (
                <p key={index}>{item.name}</p>
            ))}
        </div>
    );
}

export default App;

1. Which UseEffect will be called after every render? 1. 每次渲染后会调用哪个 UseEffect ?

Ans: According to the react official doc useEffect does care about 3 lifecycle method namely componentDidMount componentDidUpdate and componentWillUnmount . Ans:根据反应官方文档useEffect确实关心 3 个生命周期方法,即componentDidMount componentDidUpdatecomponentWillUnmount So no matter what how many useEffect you have, all the effect hooks will execute when componentMount for the first time.所以无论你有多少useEffect ,第一次componentMount时所有的效果钩子都会执行。 But useEffect will execute further, only when it's dependency get updates else it will ignore但是useEffect会进一步执行,只有当它的依赖得到更新时才会忽略

2. Why and How console.log() is called 13 times? 2. 为什么以及如何调用 console.log() 13 次?

Ans: I tried to reproduce 13 times rerendering but I am not able to do so. Ans:我试图重现 13 次重新渲染,但我无法这样做。 But yes it's rerendering multiple times because in the 2nd useEffect on every Keystore the state is updating and because of that component is rerendering several times.但是是的,它会重新渲染多次,因为在每个密钥库的第二个useEffect中,state 正在更新,并且因为该组件正在重新渲染多次。

its happening something like this它发生了这样的事情

changeName() → setName() → useEffect() → setFilter() → (on every keystore repeating same step) →...loop changeName() → setName() → useEffect() → setFilter() →(在每个密钥库上重复相同的步骤)→...循环

you can try debounce or throttling which can help you to avoid continuous Keystore hit by which no of rerendering can drastically reduce您可以尝试debouncethrottling ,这可以帮助您避免连续的 Keystore 命中,从而不会大幅减少重新渲染

Instead of using console.log , there is a hack to know the number of rerendering而不是使用console.log ,有一个技巧可以知道重新渲染的数量

declare the below code in the component在组件中声明以下代码

const cunter = useRef(0);

and then in the return block add {cunter.current++} by this you can see how many times your component is actually rerendering然后在返回块中添加{cunter.current++}通过这个你可以看到你的组件实际重新渲染了多少次

3. Why the fetched data is not shown in the browser until I type something in the search bar? 3. 为什么在我在搜索栏中输入内容之前,浏览器中不显示获取的数据?

This is because in your condition your checking !filteredMonster where filteredMonster is an array and !filteredMonster will return always false instead try Array length properties这是因为在您的条件下,您正在检查!filteredMonster ,其中filteredMonster是一个数组,而!filteredMonster将始终返回false而不是尝试数组length属性

filteredMonster.length === 0

{monster && !filteredMonster && monster.map((item, index) => (
     <p key={index}>{item.name}</p>
))}

{(monster && filteredMonster.length === 0) && monster.map((item, index) => (
         <p key={index}>{item.name}</p>
))}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么每次渲染都会调用来自 `useEffect` 的清理函数? - Why is the cleanup function from `useEffect` called on every render? React Hook“useEffect”被有条件地调用。 React Hooks 必须在每个组件渲染中以完全相同的顺序调用 - React Hook "useEffect" is called conditionally. React Hooks must be called in the exact same order in every component render 哪一个具有更好的性能:在每个渲染VS上添加和删除事件侦听器VS运行useEffect来更新ref - Which one has better performance: add and remove event listener on every render VS running an useEffect to update a ref 从 useEffect 渲染调用的函数太快并中断,重新渲染后工作正常 - function called from useEffect rendering too fast and breaks, works correctly after re-render 如何避免在每次渲染时触发 useEffect? - How to avoid triggering useEffect on every render? 每次渲染时都将不同的 function 传递给 useEffect? - ReactJS 使用效果 - Different function gets passed to useEffect on every render? - ReactJS useEffect 为什么不调用 useEffect,当 props 发生变化时,会调用 render? - Why useEffect is not called, when props have changed, render is called? useEffect 在初始渲染后不触发 - useEffect does not trigger after initial render 为什么每次渲染后都会执行useEffect? - why is useEffect executing after each render? 在 useEffect 之后在 React 路由器 dom 中渲染路由 - Render route in React router dom after useEffect
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM