javascript - 在组件中使用渲染道具时,有哪些常见的陷阱可以避免无限重新渲染?
问题描述
假设我们正在使用 react-router-dom 在 react 中实现受保护的路由,我们必须牢记一些事情,例如在渲染私有路由时,组件确实会进入无限的重新渲染循环。
这条路线给我一个错误,最大调用堆栈超出反应防止无限重新渲染。这个组件有什么问题?PrivateRoute.jsx
const PrivateRoute = ({
component: Component,
isAuthenticated,
token,
...rest
}) => {
const employee = decoder(token);
return (
<Route
{...rest}
render={props =>
isAuthenticated && employee.user.emp_role === "admin" ? (
<Component {...props} />
) : (
<Redirect to="/login" />
)
}
/>
);
};
PrivateRoute.propTypes = {
isAuthenticated: PropTypes.bool
};
const mapStateToProps = state => ({
isAuthenticated: state.authReducer.isAuthenticated,
token: state.authReducer.token
});
export default connect(mapStateToProps, { loadUser })(PrivateRoute);
我正在使用从 redux 状态映射到道具,选择必要的部分,例如 isAuthenticated 和令牌,令牌用于检查可能是管理员或员工的角色,将它们放入三元运算符等。这个组件的问题在哪里?
编辑 1:App.js
//imports here
if (localStorage.token) {
setAuthToken(localStorage.token);
}
function App() {
useEffect(() => {
store.dispatch(loadUser());
}, []);
return (
<Provider store={store}>
<Router>
<Alert />
<Switch>
<Layout>
<Switch>
<Route exact path="/" component={Landing} />
<Route exact path="/login" component={Login} />
<AdminRoutes exact path="/admin" component={Admin} />
<AdminRoutes exact path="/employees" component={Employees} />
<AdminRoutes exact path="/profile" component={Profile} />
<AdminRoutes exact path="/chemists" component={Chemists} />
<AdminRoutes
exact
path="/distributors"
component={Distributors}
/>
<AdminRoutes exact path="/doctors" component={Doctors} />
<AdminRoutes exact path="/products" component={Products} />
</Switch>
</Layout>
</Switch>
<Switch>
<PrivateRoute
exact
path="/representative"
component={Representative}
/>
</Switch>
</Router>
</Provider>
);
}
export default App;
登录.jsx
const Login = ({ login, isAuthenticated, token }) => {
const [formData, handleFormData] = useState({
emp_phone: "",
emp_password: ""
});
const { emp_password, emp_phone } = formData;
const onSubmit = async e => {
e.preventDefault();
login(emp_phone, emp_password);
};
const handleLogin = e => {
handleFormData({ ...formData, [e.target.name]: e.target.value });
};
// if (isAuthenticated) {
// const employee = decoder(token);
// if (employee.user.emp_role === "admin") {
// return <Redirect to="/admin" />;
// } else return <Redirect to="/representative" />;
// }
return (
<Fragment>
<div className="w-full max-w-sm shadow-md rounded p-5 m-3 align-middle h-auto">
<form onSubmit={e => onSubmit(e)}>
<div className="field self-center">
<label className="label" htmlFor="phone">
Phone Number
</label>
<div className="control">
<input
type="text"
pattern="[0-9]*"
id="phone"
placeholder="Enter phone number"
name="emp_phone"
required
value={emp_phone}
onChange={e => handleLogin(e)}
className="input"
/>
</div>
</div>
<div className="field">
<label className="label" htmlFor="password">
Password
</label>
<div className="control">
<input
type="password"
placeholder="Enter password"
name="emp_password"
id="password"
value={emp_password}
required
onChange={e => handleLogin(e)}
className="input"
/>
</div>
</div>
<button type="submit" className="button is-primary">
Login
</button>
</form>
</div>
</Fragment>
);
};
Login.propTypes = {
login: PropTypes.func.isRequired,
isAuthenticated: PropTypes.bool
};
const mapStateToProps = state => ({
isAuthenticated: state.authReducer.isAuthenticated,
token: state.authReducer.token
});
export default connect(mapStateToProps, { login, loadUser })(Login);
解决方案
我认为问题可能是由于使用的逻辑。这也发生在我几周前。
isAuthenticated && employee.user.emp_role === "admin" ? (
<Component {...props} />
) : (
<Redirect to="/login" />
)
在上面的代码中,当为 null 或 false(从本地存储加载期间)时,isAuthenticated 的值可以为 null 多次,这会多次触发 Redirect 组件。
你能试试下面的逻辑吗
!isAuthenticated && employee.user.emp_role !== "admin" ? (
<Redirect to="/login" />
) : (
<Component {...props} />
)
推荐阅读
- sql - 如何将 Toad Data 模型导入 Erwin Data Modeler?
- python - Python:无法过滤 CSV,ValueError:只能将大小为 1 的数组转换为 Python 标量
- r - har_agg(RM1, period, nperiods) 中的错误:与请求的类型不兼容:[type=character; 目标=双]
- qt - 使用鼠标区域或 DropArea 的 ListView 多选
- nuxt.js - 如何在 Nuxt 中将路由器内容渲染到 index.html
- javascript - 在页面加载 Javascript 时将 div 内容显示为默认值
- jenkins - 你能在一个 Jenkins 阶段加载一个 groovy 文件吗?运行函数;并使用 @groovy.transform.Field 在多个 Jenkins 阶段共享数据
- javascript - 状态变化未反映在 Next.Js 中的功能中
- sqlalchemy - SqlAlchemy:未定义此子句的布尔值
- c# - Resharper 打破了 Visual Studio 2019 的功能