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