reactjs - useEffect hook 在路由更改时修复依赖数组
问题描述
我正面临功能组件的问题。我正在使用一个react-router-dom
包来处理路线。我所拥有的是一个包含链接和按钮的列表,当我们单击按钮时,会打开一个下拉列表。此下拉列表还包含链接。
- 每当用户更改路线时,所有下拉菜单都会关闭。
- 每当打开新的下拉菜单时,所有其他下拉菜单也会关闭。
我如何管理这些下拉菜单的状态?
我将每个下拉列表的状态视为一个单独的对象,并且onClick
侦听器将key
/property
作为具有布尔值的参数传递。基于该值,将在下拉列表中添加一个类。
我已经在类组件的帮助下实现了这一点。
类组件:
import React, { Component } from "react";
import { Link, withRouter } from "react-router-dom";
class ToggleClass extends Component {
state = {};
toggle = dropdownName => {
// If it has the true value then turn into false, It is a behavior of a toggle.
if (this.state[dropdownName]) {
this.setState({ [dropdownName]: false });
}
// If there is not any dropdown is opened it means state object is empty
// Object.keys will return an empty array then please open that dropdown.
else if (Object.keys(this.state).length === 0) {
this.setState({ [dropdownName]: true });
}
// Else block will ony trigger when the user clicked on other dropdown,
// then close the last dropdown and just open the new one
else {
Object.keys(this.state).forEach(i => {
this.setState({ [i]: false });
});
this.setState({ [dropdownName]: true });
}
};
onRouteChanged = () => {
// Take a state object and convert all its keys into an array
// and set it to false whenever a route changes.
Object.keys(this.state).forEach(i => {
// pageMenu: false
this.setState({ [i]: false });
});
};
componentDidUpdate(prevProps, prevState, snapshot) {
if (this.props.location !== prevProps.location) {
this.onRouteChanged();
}
}
componentDidMount() {
this.onRouteChanged();
}
render() {
return (
<ul className="list">
<li>
<Link to="/link1">Link 1</Link>
</li>
<li>
<button onClick={() => this.toggle("dropdown1")}>Dropdown 1</button>
<ul className={this.state["dropdown1"] ? "open" : "hide"}>
<li>
<Link to="/link2">Link 2</Link>
</li>
<li>
<Link to="/link3">Link 3</Link>
</li>
</ul>
</li>
<li>
<button onClick={() => this.toggle("dropdown2")}>Dropdown 2</button>
<ul className={this.state["dropdown2"] ? "open" : "hide"}>
<li>
<Link to="/link4">Link 4</Link>
</li>
<li>
<Link to="/link5">Link 5</Link>
</li>
</ul>
</li>
</ul>
);
}
}
export default withRouter(ToggleClass);
但是问题出在使用钩子的功能组件上。react-router-dom
有一个名为useLocation的钩子,它返回当前的pathname
. 但是onRouteChanged
功能正在更新状态。我不能在useEffect
钩子里面使用这个函数,它变成了一个无限循环。
useEffect(() => {
onRouteChanged();
}, [location, onRouteChanged]);
但是如果我onRouteChanged
从依赖数组中删除,那么 linter 会警告这个
React Hook useEffect has a missing dependency: 'onRouteChanged'. Either include it or remove the dependency array react-hooks/exhaustive-deps
useEffect(() => {
onRouteChanged();
}, [location]);
功能组件:
import React, { useEffect, useState } from "react";
import { Link, useLocation } from "react-router-dom";
const ToggleFunc = () => {
const location = useLocation();
const [state, setState] = useState({});
const onRouteChanged = () => {
Object.keys(state).forEach(i => {
setState({ [i]: false });
});
};
const toggle = dropdownName => {
if (state[dropdownName]) {
setState({ [dropdownName]: false });
} else if (Object.keys(state).length === 0) {
setState({ [dropdownName]: true });
} else {
Object.keys(state).forEach(i => {
setState({ [i]: false });
});
setState({ [dropdownName]: true });
}
};
useEffect(() => {
onRouteChanged();
}, [location]);
return (
<ul className="list">
<li>
<Link to="/link1">Link 1</Link>
</li>
<li>
<button onClick={() => toggle("dropdown1")}>Box 1</button>
<ul className={state["dropdown1"] ? "open" : "hide"}>
<li>
<Link to="/link2">Link 2</Link>
</li>
<li>
<Link to="/link3">Link 3</Link>
</li>
</ul>
</li>
<li>
<button onClick={() => toggle("dropdown2")}>Box 2</button>
<ul className={state["dropdown2"] ? "open" : "hide"}>
<li>
<Link to="/link4">Link 4</Link>
</li>
<li>
<Link to="/link5">Link 5</Link>
</li>
</ul>
</li>
</ul>
);
};
export default ToggleFunc;
你能指导我解决这些错误的最佳方法是什么?
解决方案
我认为您必须重构状态结构和切换实现,这是固定沙箱示例(我没有更改状态结构只是解决了您的问题)。
推荐阅读
- blazor - How to create a merchant and customer registration in blazor with identity server?
- c# - 推荐比例更高的显示器上的 RDLC 问题
- r - 如何在 R 中居中对齐 KM 绘图标题?
- asp.net-core - IdentityServer4:[Authorize(Roles = "Admin")] 即使 JWT 令牌具有 {"role": "Admin"} 声明,也不授予管理员用户访问权限
- javascript - 组件是否渲染了两次?是codeandbox问题吗?
- django - 如何在 django 中正确显示 Flash 消息
- javascript - 如何在javascript中访问块外的变量?
- mysql - 使用 SQL 显示 WooCommerce 产品
- office-js - Microsoft Office Add in Javascript,MarkAsJunk 请求返回 GenericResponseError
- laravel - 如何在 laravel 的循环中使用 save() 方法