我是React的初学者,遇到了一些问题。我对此代码有几个疑问。
每次渲染后将调用哪个UseEffect?
为什么和如何调用console.log()13次?(请在下面的屏幕截图中找到)
为什么直到在搜索栏中输入内容后,浏览器中才会显示获取的数据?
App.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;
答案 0 :(得分:0)
请尝试一下。 fetchData()将仅运行1,searchName将在您在屏幕上键入的次数相同。
提示:为防止这种情况。在用户完成键入后仅添加一次渲染,而不是用户按键盘键的N次渲染,请添加timeoutdelay。
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;
这正在使用Reducer,删除了状态的使用。
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 :(得分:0)
1。每次渲染后将调用哪个UseEffect?
答案:根据react official doc useEffect
确实关心3个生命周期方法,即componentDidMount
componentDidUpdate
和componentWillUnmount
。因此,无论您有多少useEffect
,所有效果挂钩都将在componentMount首次执行时执行。但是useEffect
仅在依赖项获得更新时才会进一步执行,否则它将忽略
2。为什么和如何调用console.log()13次?
答案::我尝试重现13次重渲染,但无法做到。但是,是的,它要重新渲染多次,因为在每个Keystore的第二个useEffect
中,状态都在更新,并且由于该组件要多次渲染。
它发生了这样的事情
changeName()→setName()→useEffect()→setFilter()→(在重复相同步骤的每个密钥库上)→... loop
您可以尝试debounce
或throttling
,这可以帮助您避免连续的Keystore命中,从而避免重新渲染而造成的损失。
代替使用 console.log ,有一种黑客可以知道重新渲染的次数
在组件中声明以下代码
const cunter = useRef(0);
,然后在return块中添加{cunter.current++}
,您可以看到组件实际重新渲染了多少次
3。为什么直到我在搜索栏中输入某些内容后,浏览器中才会显示获取的数据?
这是因为在您的条件下,您检查!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>
))}