React Hooks:setState,什么时候真正生效?



所以我试图理解 React Hooks 以及如何使用它们。我可以在组件中进行获取,如下所示:

var [pages,setPages] = useState();
var [page,setPage] = useState();
async function fetchData() {
await fetch(`https://myBackend/pages`)
.then(response => response.json())
.then(response => {
setPages(response); 
console.log(pages[0].title);    
})
.then(()=>{
// AT THIS STAGE, pages IS UNDEFINED
setPage(pages.filter(singlepage=> {
return singlepage.url == props.match.params.url;
}))
}
.catch(err => setErrors(err));
}
useEffect(() => {
fetchData();
console.log(pages[0].title);   
return () => {
console.log('unmounting...');
}
},[]);

我调用我的后端以获取所有页面,这工作正常,就好像我编码pages[0].title它会呈现一样。但是当我尝试在useEffect钩子中访问pages中的特定值时,对我来说分配page,它给了我pages未定义的错误。我的控制台日志记录使这一点显而易见。

我希望在页面加载之前在"组件安装"上定义pagepages。所以我的问题是setPages什么时候真正设置页面?我是否可以在useEffect中分配两者,并基于彼此分配?

异步操作需要时间。理论上可以经过不确定的时间。因此,无法保证在挂载组件之前获取数据。

相反,您需要表现得好像数据可能是未定义的,并且具有处理该数据的应用程序的状态。

至于在调用setPages后立即访问页面变量,这也将失败,因为 React 实际上是异步运行重新渲染的。

即使它同时运行,也有一种叫做closures的东西,javascript 在创建函数时会拉入函数周围的所有变量,以便函数始终可以访问这些变量。React Hooks 的工作原理是利用这些闭包来仅访问组件渲染/重新渲染时的变量。之所以会这样,是因为每次重新渲染时,组件中的所有函数都会重新创建,从而创建新的闭包。

所以,这意味着在使用 React 时,你需要牢记这些概念。

至于你的代码,Dlucidione设置的结果解决方案是你最好的选择之一,除了设置一个单独的useEffect来更新pagepages发生变化时。

const history = useHistory(); //from react-router-dom
useEffect(() => {
async function fetchData() {
return await fetch(`https://myBackend/pages`)
.then((response) => response.json())
.then((response) => {
setPages(response);
})
.catch((err) => setErrors(err));
}
fetchData();
return () => {
console.log('unmounting...');
};
}, []);
useEffect(() => {
const url = props.match.params.url;
if (!pages || !url) return;
// Using Array#find here because I assume based on the name, you want one page rather than an array
const page = pages.find((singlepage) => {
return singlepage.url === url;
});
if (!page) {
// This will change the route if a page isn't found.
history.push('/404');
}
setPage(page);
}, [pages, props.match.params.url, history]);

Redirecthistory.push的工作方式不同。Redirect是声明性导航方法,而history.push是编程方法。

history.push的用法示例:

if (!page) {
// This will change the route if a page isn't found.
history.push('/404');
}

重要提示,只要您可以将 history 对象传递给那里,就可以在代码中的任何位置使用。我以前也曾在 redux thunks 中使用过它。

Redirect在挂载时不重定向的示例用法:

if(!pages && !page){
return <Redirect to="/404"/>
}

或者在某些 JSX 中:

<div>
{!pages && !page && <Redirect to="/404"/>}
</div>

必须呈现重定向,这意味着它只能在组件的 return 语句中使用。

我理解它的方式:重定向基于如果 在安装过程中可以找到单个页面,因此 重定向过程也必须在安装过程中进行检查 在渲染任何要重定向或不重定向的内容之前。

这是正确的。当重定向本身装载或更新时,如果条件正确,它将重定向。如果重定向上有pathfrom道具(它们是彼此的别名(,那么这会限制重定向仅在该路径匹配时才起作用。如果路径不匹配,重定向将不执行任何操作,直到路径更改为匹配(或者当然,它会卸载(。

在后台,重定向只是在 componentDidMount 和 componentDidUpdate 中调用history.pushhistory.replace(通过生命周期组件(,所以你可以随心所欲。

useEffect(() => {
const fetchData = async () => {
try {
// Make a first request
const result = await axios.get(`firstUrl`);
setPages(result);
// here you can use result or pages to do other operation
setPage(result.filter(singlepage=> {
return singlepage.url == props.match.params.url;
or 
setPage(pages.filter(singlepage=> {
return singlepage.url == props.match.params.url;
}))
} catch (e) {
// Handle error here
}
};
fetchData();
}, []);

相关内容

  • 没有找到相关文章

最新更新