Javascript 将componentDidMount转换为useEffect
我试图学习React钩子,并试图将现有的代码库转换为使用钩子,但我感到困惑。 在Javascript 将componentDidMount转换为useEffect,javascript,reactjs,react-hooks,use-effect,react-component,Javascript,Reactjs,React Hooks,Use Effect,React Component,我试图学习React钩子,并试图将现有的代码库转换为使用钩子,但我感到困惑。 在useffect内设置状态正常吗?如果我这样做,我会导致可怕的无限循环吗 import React, { useState, useEffect } from 'react'; import App from 'next/app'; import Layout from './../components/Layout'; function MyApp({ Component, pageProps }) {
useffect
内设置状态正常吗?如果我这样做,我会导致可怕的无限循环吗
import React, { useState, useEffect } from 'react';
import App from 'next/app';
import Layout from './../components/Layout';
function MyApp({ Component, pageProps }) {
const [ cart, setCart ] = useState([]);
const addToCart = (product) => {
setCart((prevCartState) => {
return [ ...prevCartState, product ];
});
localStorage.setItem('cart', JSON.stringify(cart));
};
//mimicking componentDidMount to run some effect using useEffect
//useEffect(() => setCount((currentCount) => currentCount + 1), []);
useEffect(() => {
const cartCache = JSON.parse(localStorage.getItem('cart'));
//cart = cartCache; Good or bad?
cartCache || setCart(() =>{
});
}, []);
return <Component {...pageProps} />;
}
import React,{useState,useffect}来自“React”;
从“下一个/应用程序”导入应用程序;
从“/../components/Layout”导入布局;
函数MyApp({Component,pageProps}){
const[cart,setCart]=useState([]);
const addToCart=(产品)=>{
setCart((prevCartState)=>{
返回[…状态、产品];
});
setItem('cart',JSON.stringify(cart));
};
//使用useEffect模拟componentDidMount运行某些效果
//useEffect(()=>setCount((currentCount)=>currentCount+1),[]);
useffect(()=>{
const cartCache=JSON.parse(localStorage.getItem('cart'));
//cart=cartCache;好还是坏?
cartCache | | setCart(()=>{
});
}, []);
回来
}
我的原始基于类的组件:
/*
export default class MyApp extends App {
state = {
cart: []
}
componentDidMount = () => {
const cart = JSON.parse(localStorage.getItem('cart'));
if (cart) {
this.setState({
cart
});
}
};
addToCart = (product) => {
this.setState({
cart: [...this.state.cart, product]
});
localStorage.setItem('cart', JSON.stringify(this.state.cart));
}
render() {
const { Component, pageProps } = this.props
return (
<contextCart.Provider value={{ cart: this.state.cart, addToCart: this.addToCart }}>
<Layout>
<Component {...pageProps} />
</Layout>
</contextCart.Provider>
)
}
}*/
/*
导出默认类MyApp扩展应用程序{
状态={
购物车:[]
}
componentDidMount=()=>{
const cart=JSON.parse(localStorage.getItem('cart'));
如果(购物车){
这是我的国家({
运货马车
});
}
};
addToCart=(产品)=>{
这是我的国家({
购物车:[…this.state.cart,产品]
});
setItem('cart',JSON.stringify(this.state.cart));
}
render(){
const{Component,pageProps}=this.props
返回(
)
}
}*/
可以在useffect
中设置状态,只要不监听依赖项数组中相同字段的更改。在您的特定情况下,只调用一次useffect
(因为您传递了一个空的依赖项数组)
添加第二个useffect
来收听cart
更改并使localStorage
保持最新也是很酷的
useEffect(() => {
localStorage.setItem('cart', JSON.stringify(cart));
}, [cart]);
由于是一个同步调用,因此在这种情况下,您还可以使用useState
的函数回调版本来设置初始值。这样,您就不需要使用useffect
。通常,如果可能的话,我会尽量避免在我的功能组件中引入任何新的副作用
您可以尝试以下操作:
const [ cart, setCart ] = useState(() => {
const cartCache = JSON.parse(localStorage.getItem('cart'));
if (cartCache) {
return cartCache;
}
localStorage.setItem('cart', JSON.stringify([]));
return [];
});
这样,如果localStorage
中缺少cart
元素,则代码将使用默认的[]
空数组创建它,并为您的状态设置它。在其他情况下,它将设置存储中的状态值
请注意:在收听
购物车
状态更改以保持本地存储
与useffect
保持最新方面,我也同意。我的建议仅针对初始状态。我同意您的问题的“倾听变化”部分,即useffect
,这就是为什么我对这个答案投了赞成票。请检查我的答案,您认为如何按照我的建议在useState
中设置初始状态,而不是使用useffect
?谢谢那么const cartlocache=JSON.parse(localStorage.getItem('cart'))| |[]呢;const[cart,setCart]=useState(cartLocalCache)然后使用effect通过@kind user?@AJSwift的推荐来监听购物车的更改。这很酷,你也可以做setCart(cartCache | |[])
@kinduser这是一个很好的组合,我相信建议的答案。谢谢你,回答得很好
const [ cart, setCart ] = useState(() => {
const cartCache = JSON.parse(localStorage.getItem('cart'));
if (cartCache) {
return cartCache;
}
localStorage.setItem('cart', JSON.stringify([]));
return [];
});