![](/img/trans.png)
[英]Run function in useeffect when state changes after 1 second if no other changes
[英]ReactJS: useEffect is not run when the url changes
我有一个 ReactJS 网站,但我仍然是一个使用它的菜鸟。
我有 2 个组件
/
页面,它必须在向 Web 服务器发出请求后呈现,当用户到达该路由时,我为此使用了 useEffect。/mostraMaterie/:id
必须在向 Web 服务器发出另一个请求后呈现。第一个组件像魅力一样工作,而第二个组件不会触发 useEffect 函数。
当用户点击/
组件上的按钮时,它会被重定向到/mostraMateria/:id
并带有相应的 id。
问题是/mostraMateria
组件我有另一个 useEffect 函数,但它没有被触发。
正如评论中所建议的,这是 JSFiddle mostraMaterie.js 中的 mostraMateria 文件
App.js处理用户连接
import React from "react";
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
import MostraMaterie from "./Contenuti/MostraMaterie";
import "./App.css";
import Main from "./Contenuti/Main";
function App() {
return (
<Router>
<Switch>
<Route path="/mostraMateria/:id" component={MostraMaterie} />{" "}
<Route exact path="/" component={Main} />{" "}
</Switch>{" "}
</Router>
);
}
export default App;
Main.js处理页面渲染,如果位置是/
并且工作正常。
import React, { useEffect, useState } from "react";
import { Link } from "react-router-dom";
import Indirizzi from "./Indirizzi";
import Bottone from "../Util/Bottone";
import "../App.css";
import FullNavBar from "../NavBar/FullNavBar";
function Main() {
const [indirizzi, cambiaIndirizzi] = useState([]);
const fetchIndirizzi = () => {
async function prendiIndirizzi() {
let indirizzi = await fetch(
"https://vps.lellovitiello.tk/Riassunty/API/indirizzi.php"
);
let ind = await indirizzi.json();
for (let i = 0; i < ind.length; i++) {
async function prendiMaterie() {
let materie = await fetch(
`https://vps.lellovitiello.tk/Riassunty/API/materie.php?indirizzo=${ind[i].Indirizzo}`
);
materie = await materie.json();
for (let materia of materie) {
Object.defineProperty(
materia,
"nome",
Object.getOwnPropertyDescriptor(materia, "Materia")
);
delete materia["Materia"];
Object.defineProperty(
materia,
"id",
Object.getOwnPropertyDescriptor(materia, "IDMateria")
);
delete materia["IDMateria"];
delete materia["Indirizzo"];
}
Object.defineProperty(
ind[i],
"nome",
Object.getOwnPropertyDescriptor(ind[i], "Indirizzo")
);
delete ind[i]["Indirizzo"];
Object.assign(ind[i], { dati: materie });
Object.assign(ind[i], { id: i });
}
await prendiMaterie();
}
console.log("Main.js", ind);
cambiaIndirizzi(ind);
}
prendiIndirizzi();
};
useEffect(fetchIndirizzi, []);
return (
<React.Fragment>
<FullNavBar elementi={indirizzi} />{" "}
<Link to="/Login">
<Bottone TestoBottone="Per caricare un riassunto" />
</Link>{" "}
{indirizzi.map(indirizzo => {
console.log(indirizzo);
return <Indirizzi dati={indirizzo} />;
})}
</React.Fragment>
);
}
export default Main;
如果位置是/mostraMaterie/:id
并且不起作用,则MostraMaterie.js处理页面呈现。
import React, { useEffect, useState } from "react";
import "../App.css";
import history from "../Util/history";
import { Link } from "react-router-dom";
import FullNavBar from "../NavBar/FullNavBar";
import Indirizzi from "./Indirizzi";
import Bottone from "../Util/Bottone";
function MostraMaterie(props) {
const [anni, cambiaAnni] = useState([]);
// *** this function is never called ***
const fetchAnni = () => {
async function prendiAnni() {
let anniJson = await fetch(
"https://vps.lellovitiello.tk/Riassunty/API/ottieniAnni.php"
);
let idMateria = props.match.params.id;
let ann = [];
anniJson = await anniJson.json();
for (let anno of anniJson) {
async function prendiAnteprime() {
let anteprimeFetch = await fetch(
`https://vps.lellovitiello.tk/Riassunty/API/anteprima.php?idMateria=${idMateria}&anno=${anno}`
);
anteprimeFetch = await anteprimeFetch.json();
for (let anteprima of anteprimeFetch) {
Object.defineProperty(
anteprima,
"nome",
Object.getOwnPropertyDescriptor(anteprima, "Titolo")
);
Object.defineProperty(
anteprima,
"id",
Object.getOwnPropertyDescriptor(anteprima, "ID")
);
delete anteprima["Titolo"];
delete anteprima["ID"];
}
let annoOggetto = {
nome: anno + "",
anteprime: anteprimeFetch
};
ann.push(annoOggetto);
}
await prendiAnteprime();
}
debugger;
cambiaAnni(ann);
}
console.log("Vengo eseguito");
prendiAnni();
};
useEffect(fetchAnni, []);
console.log(history.location);
return (
<React.Fragment>
<FullNavBar indirizzi={anni} />{" "}
<Link to="/Login">
<Bottone TestoBottone="Per caricare un riassunto" />
</Link>{" "}
<h1> CIao CIAO CIAO CIAOC </h1>{" "}
{
//*** this depends on the response of the web server ***
anni.map(anno => {
console.log("Ciao");
return <Indirizzi dati={anno} />;
})}{" "}
</React.Fragment>
);
}
export default MostraMaterie;
我怎样才能使这项工作?
编辑
我已经删除了<FullNavBar indirizzi={anni} />{" "}
并且它可以工作,现在我的请求被发送到服务器并且 ``fetchAnni``` 函数被触发。
问题是,我需要我删除的一段代码,似乎<FullNavBar indirizzi={anni} />{" "}
在调用fetchAnni
之前呈现,甚至按照Artur 的建议添加了await prendiAnni
和async fetchAnni
不起作用。
我也改变了useEffect(fetchAnni, []);
to useEffect(fetchAnni, [props.location.pathname]);
那是一个字符串
第二个 useEffect arg []
:
首先:发送[]
作为 useEffect 的第二个参数会说“永远不要重新运行这个函数”(只有 2 次,在安装和卸载时)。
删除它! 这是不对的 :
您不想删除它,否则每次渲染都会调用您的效果并导致性能问题。
选择正确的 var(s) 进行跟踪:
您必须为 React 提供所有会影响您的函数重新呈现的字段,在您的情况下是“当 URL 更改时”。
提示: React 每次都会测试自上次渲染以来是否有一个变量被更新,但我们也知道非原始变量不起作用:
const a = {name: "Foo"};
const b = {name: "Foo"};
const res = (a === b); // False
因此,您必须仅选择原始值。 在您的情况下,最简单的是/:id
在您的路线上: props.match.params.id
。
useEffect(fetchAnni, [props.match.params.id]);
console.log(`Render for ID: ${props.match.params.id}`);
异步/等待
此外,您将函数prendiAnni
定义为async
但您将其称为:
console.log("Vengo eseguito");
prendiAnni();
代替
await prendiAnni();
看起来好像您将一个空数组作为第二个参数传递给 useEffect(), useEffect(fetchAnni, []);
来自https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skiping-effects
如果您只想运行效果并仅将其清理一次(在装载和卸载时),您可以传递一个空数组 ([]) 作为第二个参数。 这告诉 React 你的 effect 不依赖于来自 props 或 state 的任何值,所以它永远不需要重新运行。
如果你想在每次渲染上运行效果,你可以省略第二个参数。 如果您希望它仅在某些道具/状态值更改时运行,您可以将它们作为数组值传递到第二个参数中。
在useEffect
Hook 的依赖项数组中包含 URL。
例子:
import React, { useEffect } from 'react';
const Component = () => {
const url = window.location.pathname.split('/').pop();
useEffect(() => {
// Function will retrigger on URL change
}, [url]);
return(
<div className = 'Whatever'>Whatever</div>
);
}
export default Component;
import React, { useEffect } from 'react'
import { useHistory } from 'react-router-dom'
const Root = () => {
const history = useHistory()
useEffect(() => {
history.listen((location) => {
console.log(`You changed the page to: ${location.pathname}`)
})
}, [history])
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.