Tengo un componente de clase React con el siguiente código (solo se incluyen las cosas relevantes):
class SomePage extends Component { constructor(props) { super(props); this.state = { stuff: "" } } // NOTE: this.props.data comes from mapStateToProps from below componentDidMount() { console.log(this.props.data) // shows up as "undefined" } componentDidUpdate(prevProps) { console.log(this.props.data); // has the data I need if((prevProps.data !== this.props.data) && this.props.data.part1 && this.props.data.part2) { // LINE A console.log("inside if statement"); // never entered this.setState({stuff: this.props.data.part2}); // need to set state here!! } } render () { return ( {this.state.stuff} ) } const mapStateToProps = state => { return { data: state.analysisReducer.data; } } export default connect(mapStateToProps, null)(SomePage); Si cambio el componentDidUpdate desde arriba para no incluir prevProps en la declaración if, como se muestra a continuación, entonces se llama a setState infinitamente.
componentDidUpdate(prevProps) { console.log(this.props.data); // has the data I need if(this.props.data && this.props.data.part1 && this.props.data.part2) { // LINE B - removed the "prevProps.data !==" this.setState({stuff: this.props.data.part2}); // entered, but called infinitely } }Problema : como se muestra arriba, la línea A nunca se ingresa y el estado establecido en la línea B provoca un bucle infinito.
Objetivo : necesito llamar a setState solo una vez, ya sea cuando tenga acceso a this.props.data una vez que sus datos estén disponibles o cuando this.props.data cambie de su estado anterior.
¿Cómo hago esto?
No está modificando los accesorios de datos que está pasando, por lo que no necesita poner eso en el estado de componentes. Puede omitir todas las cosas del estado y simplemente usar los accesorios que está pasando.
// Agregado después del comentario Todavía no está editando los datos pasados desde props, pero aquí hay un ejemplo de cómo hacer lo que quiere con un componente funcional.
import { useEffect, useState } from "react"; export default function App() { const [input, setInput] = useState(''); return ( <div className="App"> <h1>Hello</h1> <input type='text' value={input} onChange={(e) => setInput(e.target.value)} /> <Page data={{ part2: input }} /> </div> ); } const Page = (props) => { const [state, setState] = useState({}); useEffect(() => { console.log("useEffect"); setState({ ...state, stuff: props.data.part2 }); }, [props.data.part2]); return <div>{state.stuff}</div>; };Codesandbox: https://codesandbox.io/s/adoring-varahamihira-bgqpby