Estoy tratando de crear una aplicación de lista de tareas pendientes. Los elementos se mantendrán como variables de estado en App.js y luego esta variable de estado se pasará a otro componente (ItemDisplay) que la mostrará. Pero cada vez que agrego un elemento al estado, el componente ItemDisplay no se actualiza. ¿Qué estoy haciendo mal?
Aplicación.js
import './App.css'; import { useEffect, useState } from 'react'; import Textarea from './textArea'; import ItemDisplay from './itemDisplay'; function App() { const [items,setItems] = useState([]) const addText = (e,val)=>{ // const tempval = items // setItems(tempval.push(val)) // console.log(items) var newarr = items newarr.push(val) setItems(newarr) // console.log(items) // console.log(newarr) } return ( <div className="container"> <div className="heading"> <h2>Todo list</h2> </div> <Textarea addText={addText}></Textarea> <ItemDisplay items={items}></ItemDisplay> </div> ); } export default App;ElementoDsiplay.js
const items = props.items //console.log(props.items) return ( <div> {items.map(item=>(<p>item</p>))} </div> ); } export default ItemDisplay;TextArea.js
const Textarea = (props) => { const [todoVal, setTodoval] = useState('') return ( <div className="textportion"> <input type="text" value = {todoVal} onChange={(e)=>setTodoval(e.target.value)} placeholder="Enter the list here"> </input> <button onClick={(e)=>{props.addText(e,todoVal)}}>Add</button> </div> ); } export default Textarea;En su ItemDisplay.js, está asignando props.items a una variable. Esto sucede solo una vez. En primer lugar, para que el componente se actualice automáticamente, debe asignar props.items a una variable de estado mediante useState hook. Si necesita actualizar el componente cada vez que cambia props.items, debe usar el gancho useEffect:
const [items, setItems] = useState([]) useEffect(()=>{ setItems(props.items) }, [props.items]) return ( <div> {items.map(item=>(<p>item</p>))} </div> );Pruebe esto en su componente ItemDisplay.js. Importe los ganchos useState y useEffect en el componente.
Ya, tienes razón. No se actualiza porque en su App.js está asignando var newarr = items . Esto realmente asigna una referencia a la matriz de elementos en newarr. En su lugar, cámbielo a var newarr = [...items] . Esto crea una copia del mismo. Los códigos modificados son los siguientes:
import { useState } from 'react'; import Textarea from './TextArea'; import ItemDisplay from './ItemDisplay'; function App() { const [items, setItems] = useState([]) const addText = (e, val) => { var newarr = [...items] newarr.push(val) setItems(newarr) } return ( <div className="container"> <div className="heading"> <h2>Todo list</h2> </div> <Textarea addText={addText}></Textarea> <ItemDisplay items={items}></ItemDisplay> </div> ); } export default App; import React from 'react' import { useState, useEffect } from 'react' function ItemDisplay(props) { const [items, setItems] = useState([]) useEffect(() => { console.log('updating') setItems(props.items) }, [props.items]) return ( <div> {items.map(item => (<p>{item}</p>))} </div> ); } export default ItemDisplay import { useState } from "react"; const Textarea = (props) => { const [todoVal, setTodoval] = useState('') return ( <div className="textportion"> <input type="text" value={todoVal} onChange={(e) => setTodoval(e.target.value)} placeholder="Enter the list here"> </input> <button onClick={(e) => { props.addText(e, todoVal) }}>Add</button> </div> ); } export default Textarea;Esto debería solucionar tu problema.
Debe crear una nueva matriz para activar una actualización. Agregue un elemento como este: setItems(prevItems => [...prevItems, val]) . Esto creará una nueva matriz, copiará los elementos existentes y agregará el nuevo valor al final.
Además, debe agregar una key única a cada elemento representado por un bucle para que React sepa cuándo volver a procesar. Así: {items.map(item => (<p key={item}>{item}</p>))}
Creo que mantiene la referencia de matriz en el componente de la aplicación para que el componente secundario no se actualice, actualice la matriz de elementos de manera inmutable
const addText = (e,val)=>{ var newarr = newarr.concat([val]) setItems(newarr) }