Javascript 将componentDidMount转换为useEffect

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 }) {

我试图学习React钩子,并试图将现有的代码库转换为使用钩子,但我感到困惑。 在
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 [];
});