[英]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.我对此代码有几个疑问。
Which UseEffect will be called after every render?每次渲染后会调用哪个 UseEffect ?
Why and How console.log() is called 13 times?(Please find the screenshot below)为什么以及如何调用 console.log() 13 次?(请在下面找到屏幕截图)
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
componentDidUpdate
和componentWillUnmount
。 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您可以尝试debounce
或throttling
,这可以帮助您避免连续的 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.