Estoy tratando de agregar un nuevo elemento li al elemento ul en el div de retorno de CommentList. Debe contener la entrada del usuario del campo <input type="text" /> .
Recibo este error: 'No se pueden leer las propiedades de nulo (leyendo 'valor')'
Probé algunas cosas, como crear nuevos elementos li en Enviar y agregarlos al elemento ul, pero no tuve suerte.
Resultado previsto
Al hacer clic el usuario, cualquier valor que esté en el campo de texto de entrada, creará un nuevo elemento li y lo agregará al elemento ul.
const CommentList = (props) => { const [children, setChildren] = useState([]); setChildren((oldArray) => [ ...oldArray, document.querySelector("input[type='text']").value, ]); return (<div> <form> <input type="text" /> <input onSubmit={setChildren} type="button" value="Post" /> </form> <ul> </ul> </div>); }No debería mezclar React con métodos DOM nativos.
Este ejemplo:
Tiene un estado para la lista de elementos y otro para el estado actual de la entrada.
Cuando el valor de la entrada cambia, el estado de la input se actualiza.
Cuando se hace clic en el botón, el estado de los items se actualiza con el estado de input , el estado de input se restablece y el elemento de entrada se reenfoca. ( useRef )
(Nota: usar <input> sin <form> es HTML válido, por eso podemos usar onClick en lugar de onSubmit ).
const { useState, useRef } = React; function Example() { // Create a new reference which will be applied // to the input element const ref = useRef(null); // Initialise the states const [ items, setItems ] = useState([]); const [ input, setInput ] = useState(''); // When the input value changes update // the `input` state function handleChange(e) { setInput(e.target.value); } // When the button is clicked add the // `input` state to the `items` state, // reset the `input` state, and focus on // the input element function handleClick() { setItems([...items, input]); setInput(''); ref.current.focus(); } // `map` over the items array to produce an // array of list items return ( <div> <input ref={ref} onChange={handleChange} value={input} /> <button onClick={handleClick}>Save</button> <ul>{items.map(item => <li>{item}</li>)}</ul> </div> ); } ReactDOM.render( <Example />, document.getElementById('react') ); <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script> <div id="react"></div>El onSubmit tiene que estar en el formulario. El controlador onSubmit acepta un parámetro de evento, no puede usar el setter setChildren de esta manera.
Debe usar el estado para controlar el valor de entrada (el mejor enfoque aquí)
Finalmente, debe asignar el estado de sus children a JSX para representarlo en su devolución
intente esto (no probé el código, pero la idea está aquí):
const CommentList = (props) => { const [children, setChildren] = useState([]); const [inputValue, setInputValue] = useState(""); return (<div> <form onSubmit={(e) => { e.preventDefault(); setChildren((oldArray) => [ ...oldArray, inputValue ]); setInputValue(""); }}> <input type="text" value={inputValue} onChange={e => setInputValue(e.target.value)} /> <input type="button" value="Post" /> </form> <ul> {children.map((child, index) => <li key={index}>{child}</li>)} </ul> </div>); }Ve a echar un vistazo al documento de reacción:
Primero cambie el nombre de su función onSubmit de setChildren porque es la misma función que se usa para actualizar el estado de los niños y cambie onSubmit a onClick. Prueba esto en su lugar: -
export default function App() { const [children, setChildren] = useState([]); const handleSetChildren = (e) => { e.preventDefault(); setChildren((oldArray) => [ ...oldArray, document.querySelector("input[type='text']").value ]); }; return ( <div> <form> <input type="text" /> <input onClick={handleSetChildren} type="submit" value="Post" /> </form> <ul> {children.map((child) => ( <li key={child}>{child}</li> ))} </ul> </div> ); }