javascript - 对 history.push 和 useEffect 反应无限递归
问题描述
我对反应有点陌生,我似乎有鸡和蛋的问题。我想让浏览器 URL 中的查询参数与useState
页面中的变量同步。我遇到的问题是,当我useEffect
做了一个history.push
then react 更新触发另一个变量history.push
并发生无限递归时。这是我尝试解决的方法,但我必须有重复的代码。一个副本在内部useEffect
,另一个副本在外部,useEffect
因此我可以在不触发无限递归的情况下使用它。
我以为我读到我可以memoize
做点什么,但我不确定。我怎样才能避免这个重复的代码?
import {useState, useEffect} from "react";
import {useHistory, useLocation} from "react-router-dom";
function useQuery() {
return new URLSearchParams(useLocation().search);
}
export default function Home(props) {
const history = useHistory();
const query = useQuery();
const [something, setSomething] = useState('');
const [term, setTerm] = useState(query.get('term') === null ? '' : query.get('term'));
const [urlParams, setUrlParams] = useState(duplicateCode());
// this duplication of the code below
function duplicateCode() {
const params = new URLSearchParams();
if ( term !== '' ) params.append('term', term);
return params;
}
// this duplication of the code above
useEffect(() => {
const params = new URLSearchParams();
if ( term !== '' ) params.append('term', term);
setUrlParams(params);
},[term]);
// separate useEffect for term and history.push else get infinite recursion
useEffect(() => {
history.push('?' + urlParams);
// simulate API call
setSomething(urlParams.toString().replace("term=", ""));
},[history, urlParams]);
function handleSubmit(event) {
setTerm(''+Math.random()*100);
event.preventDefault();
}
return (
<div>
<p>Term = {something}</p>
<form onSubmit={handleSubmit}><button>Button</button></form>
</div>
);
}
和 App.js 以防万一。
import {React} from "react";
import { BrowserRouter as Router, Route } from "react-router-dom";
import Home from "./Home";
export default function App(props) {
return (
<section className="App">
<Router>
<Route exact path="/" component={Home} />
</Router>
</section>
);
};
解决方案
您可以在道具上使用 useEffect 并在那里解析查询字符串。react 路由器会将默认 props 发送到名为 location 的组件并匹配(路径中没有任何复杂的东西,所以没有匹配)
代码:
import { React } from "react";
import { BrowserRouter as Router, Route } from "react-router-dom";
import queryString from 'query-string'
import { useState, useEffect} from "react";
import { useHistory } from "react-router-dom";
function Home(props) {
const history = useHistory();
const [term, setTerm] = useState(props.termIn === null ? "" : props.termIn);
useEffect(() => {
const params = queryString.parse(props.location.search);
if (params.term) {
setTerm(params.term);
}
}, [props]);
function handleSubmit(event) {
history.push("/?term=" + (Math.random() * 100));
event.preventDefault();
}
return (
<div>
<p>
Term = {term}
</p>
<form onSubmit={handleSubmit}>
<button>Button</button>
</form>
</div>
);
}
export default function App(props) {
return (
<section className="App">
<Router>
<Route
path="/"
component={Home}
/>
</Router>
</section>
);
}
推荐阅读
- c++ - Invalid use of non-static member function c++ thread linux
- java - Spring如何在Spring上下文中使用非托管外部库类
- c# - MassTransit 可以用于工作队列场景吗?
- python - 如何获取运行 ipynb 文件的路径?
- javascript - 否则,相同输出的更多变量(JS)
- java - 以毫秒为单位计算差异需要时间
- python - 用于布尔值的比较运算符
- javascript - 将条码文本转换为 Microsoft Word 所需的 code128 格式以呈现为字体
- sql - 如果两行具有相同的 amt,则将“平衡”列值获取为“Y”,如果不在 SQL 查询中,则获取“N”
- c# - 使用 Linq 进行 ArrayList 转换