import './App.css';
import GoalBox from './Components/GoalBox';
import { useState, useEffect, useRef } from 'react';
function App() {
const [value, setValue] = useState('')
const inputReset = useRef(null)
let arr = [];
const submitValue = () => {
const todoList = {
'todo': value
}
console.log(todoList);
inputReset.current.value = ''; // resets input field
arr.push(todoList)
console.log('todo array', arr)
}
return (
<div className="App">
<h1>List of things to do</h1>
<input ref={inputReset} onChange={(e) => setValue(e.target.value)} />
<button onClick={submitValue}>Add New To do</button>
</div>
);
}
export default App;
So I have a functional component here, and I have useState setting the value of 'value' upon each button click. That works. What doesn't work is getting more than one value into my array. I have tried many ways, more than I want to list...
I want an array of let's say, 7 items of things to do, which I will then pass as props to and have THAT component append the DOM with a new card stating the todo items...directly after input submission...
In vanilla JS I have achieved this simply by using document.createElement('div').innerHTML = <p>${input.value}</p>
(summarized)
But I cannot figure out how to do this in react...Any help, mainly including where I am misunderstanding React usage, would be oh so great!
CodePudding user response:
Only re-render will happen when a component state changes.
Instead of using local variables (let arr = [];
), it should be another react state hook like:
const [arr, setArr] = useState([]);
Then you can add new todos as below:
setArr((prevArr) => [...prevArr, todoItem]);
function App() {
const [value, setValue] = React.useState("");
const inputReset = React.useRef(null);
const [arr, setArr] = React.useState([]);
const submitValue = () => {
const todoItem = {
todo: value
};
setArr((prevArr) => [...prevArr, todoItem]);
inputReset.current.value = ""; // resets input field
};
return (
<div className="App">
<h1>List of things to do</h1>
<input ref={inputReset} onChange={(e) => setValue(e.target.value)} />
<button onClick={submitValue}>Add New To do</button>
{arr.map(({ todo }) => (
<div key={todo}>{todo}</div>
))}
</div>
);
}
ReactDOM.render(<App />, document.querySelector('.react'));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div class='react'></div>
CodePudding user response:
You can do such task by using React state:
import './App.css';
import { useState } from 'react';
function App() {
const [value, setValue] = useState('')
const [arr, setArr] = useState([]);
const submitValue = () => {
setValue(""); // resets input field
setArr([...arr, { todo: value }]); // Use shallow copy to give a new ref
}
return (
<div className="App">
<h1>List of things to do</h1>
<input value={value} onChange={(e) => setValue(e.target.value)} />
<button onClick={submitValue}>Add New To do</button>
{arr.map(({todo}) => <p key={todo}>{todo}</p>)}
</div>
);
}
export default App;