Estoy intentando actualizar un React.Component con datos que su padre puede cambiar. Sin embargo, el componente que recibe la propiedad no actualiza su estado después de recibir la propiedad.
Por ejemplo, aquí tengo una función principal llamada Editar. Esto crea su estado para incluir un campo de título que sea "". Luego llama a Firebase y enumera todos los widgets que están en firebase para que el usuario los vea como botones. Finalmente, cuando un usuario hace clic en uno de los widgets que se enumeran, actualiza ese título para que sea el valor en firebase.
En la parte inferior de esto, tengo un componente llamado WidgetManipulation. Aquí estoy intentando pasar este título al accesorio que se utilizará. El título puede cambiar según el botón en el que haga clic el usuario para ver más información.
export default function Edit() { const [firebaseWidgetData, SetFirebaseWidgetData] = useState({ title: "", }); const [dashboardWidgets, dashboardWidgetsLoading, dashboardWidgetsError] = useCollection(collection(firestore, "Widgets"), { snapshotListenOptions: { includeMetadataChanges: true }, }); const getWidgetInfoToEdit = async ({ target: { value } }) => { const dashboardWidgetsDocRef = doc(firestore, "Widgets", value.toString()); const docSnap = await getDoc(dashboardWidgetsDocRef); SetFirebaseWidgetData(JSON.parse(JSON.stringify(docSnap.data()))); } return ( <div className={styles.container}> {dashboardWidgetsError && ( <strong>Error: {JSON.stringify(error)}</strong> )} {dashboardWidgetsLoading && <span>Collection: Loading...</span>} {dashboardWidgets && ( <span> {dashboardWidgets.docs.map((doc) => ( <button key={doc.id} value={doc.id} onClick={getWidgetInfoToEdit}> {`${doc.id} - ${doc.data().title}`} </button> ))} </span> )} <WidgetManipulation isCreate={false} firebaseWidgetData={firebaseWidgetData}></WidgetManipulation> </div> ); }El principal problema con el que me encuentro es que el componente WidgetManipulation nunca recibe un valor de estado actualizado basado en el accesorio firebaseWidgetData que transmito.
Mi código WidgetManipulation es así:
export default class WidgetManipulation extends Component { constructor(props) { super(props); this.state = { widgetData: { title: props.firebaseWidgetData.title, } } } render() { return ( <form onSubmit={this.handleSubmit}> <input id="title" name="title" type="text" required value={this.state.widgetData.title} onChange={this.handleChange} /> <label htmlFor="title">Title</label> </form> ) } }Dado que es un componente secundario, puede pasar directamente la variable prop dentro del atributo de value de esta manera:
<input id="title" name="title" type="text" required value={this.props.firebaseWidgetData.title} onChange={this.handleChange} /> React simplemente volverá a renderizar su componente principal junto con sus componentes secundarios, por lo tanto, no necesitará un estado dentro de su componente secundario. Si desea que su componente secundario tenga un estado basado en los accesorios que ha pasado, puede escuchar los cambios de accesorios usando los métodos componentDidMount y componentWillUnmount (si está usando React Class Component) y useEffect hook (si está usando React Functional Componente).
EDITAR:
Dado que el autor quiere que el campo de entrada sea utilizable, simplemente podemos pasar setFirebaseWidgetData . En su componente principal, pase la función setter:
<WidgetManipulation isCreate={false} firebaseWidgetData={firebaseWidgetData} setFirebaseWidgetData={SetFirebaseWidgetData}></WidgetManipulation>En el componente hijo, simplemente use la función setter que hemos pasado.
export default class WidgetManipulation extends Component { constructor(props) { super(props); this.state = { widgetData: { title: props.firebaseWidgetData.title, } } } render() { return ( <form onSubmit={this.handleSubmit}> <input id="title" name="title" type="text" required value={this.props.firebaseWidgetData.title} onChange={(e) => { this.props.setFirebaseWidgetData({ title: e.target.value }) }} /> <label htmlFor="title">Title</label> </form> ) } }