Using es6 it can be done like this:
this.setState({ myArray: [...this.state.myArray, 'new value'] }) //simple value
this.setState({ myArray: [...this.state.myArray, ...[1,2,3] ] }) //another array
Spread syntax
Answer from Aliaksandr Sushkevich on Stack OverflowUsing es6 it can be done like this:
this.setState({ myArray: [...this.state.myArray, 'new value'] }) //simple value
this.setState({ myArray: [...this.state.myArray, ...[1,2,3] ] }) //another array
Spread syntax
Functional Components & React Hooks
const [array,setArray] = useState([]);
Push value at the end:
setArray(oldArray => [...oldArray,newValue] );
Push value at the start:
setArray(oldArray => [newValue,...oldArray] );
How can I push an object into an array of array in react trough reducer?
Array.push() not working in React; I'm know you can't change state through push()
ReactJS Array.push function not working in setState
what is the correct way to push and pop an element to an array with useState?
I’d recommend functional updates since your state depends on previous state
setSquares(curr => […curr, “”])
More on reddit.comI am super new to react so I'm completely confused as to what's going on.
I am trying to add "question" and "answer" as an object to a certain array based on the option value selected.
Option value works, as well as payload from inputs, but I can't seem to get the logic of the return with state here:
return [
...state,
htmlArray.push({
question: action.payload.question,
answer: action.payload.answer,
}),
];it just adds number 1 to the state, as another element in state array. I know I should separate my components, but I'm new to all of this, so it's easier for now to think of it in just one file.
Here's the code with removed other cases for transparency :
import React, { useReducer, useState } from "react";
import { v4 as uuidv4 } from "uuid";
const Form = () => {
const [question, setQuestion] = useState("");
const [answer, setAnswer] = useState("");
const [option, setOption] = useState("html");
let htmlArray = [];
let cssArray = [];
let jsArray = [];
let reactArray = [];
let theoryArray = [];
const questionReducer = (state, action) => {
switch (action.type) {
case "html":
return [
...state,
htmlArray.push({
question: action.payload.question,
answer: action.payload.answer,
}),
];
default:
break;
}
};
const [state, dispatch] = useReducer(questionReducer, [
htmlArray,
cssArray,
jsArray,
reactArray,
theoryArray,
]);
console.log(state);
const handleSubmit = (e) => {
e.preventDefault();
dispatch({
type: option,
payload: {
question: question,
answer: answer,
},
});
setQuestion("");
setAnswer("");
};
return (
<form onSubmit={handleSubmit}>
<input
placeholder="question"
onChange={(e) => setQuestion(e.target.value)}
value={question}
/>
<input
placeholder="answer"
onChange={(e) => setAnswer(e.target.value)}
value={answer}
/>
<select value={option} onChange={(e) => setOption(e.target.value)}>
<option value="html">HTML</option>
<option value="css">CSS</option>
<option value="js">JS</option>
<option value="react">React</option>
<option value="theory">CS</option>
</select>
<button type="submit" value="Add question">
Enter Question
</button>
<div>{question}</div>
<div>{answer}</div>
</form>
);
};
export default Form;Do not modify state directly! In general, try to avoid mutation.
Array.prototype.push() mutates the array in-place. So essentially, when you push to an array inside setState, you mutate the original state by using push. And since push returns the new array length instead of the actual array, you're setting this.state.userAnswers to a numerical value, and this is why you're getting Uncaught TypeError: this.state.userAnswers.push is not a function(…) on the second run, because you can't push to a number.
You need to use Array.prototype.concat() instead. It doesn't mutate the original array, and returns a new array with the new concatenated elements. This is what you want to do inside setState. Your code should look something like this:
this.setState({
userAnswers: this.state.userAnswers.concat(this.state.value),
questionNumber: this.state.questionNumber + 1
}
Array.push does not returns the new array. try using
this.state.userAnswers.concat([this.state.value])
this will return new userAnswers array
References: array push and array concat
const [squares,setSquares]=useState([]);
const addSquare=()=>{
setSquares([...squares,'']);
}
const removeSquare=()=>{
setSquares(squares.pop());
}I feel like something is wrong here. Can someone help me please? :)
I’d recommend functional updates since your state depends on previous state
setSquares(curr => […curr, “”])
The way you wrote removeSquare won't work because pop() mutates the array and returns the element that was removed (not the updated array as you would want). So you want to use squares.slice(0, -1) instead.
And someone already mentioned, you should use the function that accepts previous value, like this: const adSquare = setSquare(previousValue => [...previousValue, '']) and const removeSquare = setSquare(previousValue => previousValue.slice(0,-1))
Alternatively you can use useCallback
const addSquare = useCallback(() => setSquares([...squares, '']), [squares])