0

i tried to build a TODO app with React Native

const [ enteredGoal, setEnteredGoal ] = useState("");
const [ courseGoals, setCourseGoals ] = useState([]);

const goalInputHandler = (enteredText) => {
  setEnteredGoal(enteredText);
};


const addGoalHandler = () => {
  let arrGoals = courseGoals;
  arrGoals.push(enteredGoal);
  setCourseGoals(arrGoals);
};

return (
    <View style={styles.screen}>
      <View style={styles.inputContainer}>
        <TextInput style={styles.input} onChangeText={goalInputHandler}/>
        <Button title="ADD" onPress={addGoalHandler}/>
      </View>
      <View>
        { 
          courseGoals.map((goal) => {
            <View key={goal} style={styles.listItem}><Text>{goal}</Text></View>
          })
        }
      </View>
    </View>
  );

the idea is to list the setCourseGoals array, but apparently after assigning a new text, it doesn't list anything. Its not until the text changes that the list is re-rendered. Any idea on why this happens?? the "useState" function is asynchronous, which assigns the value after rendering? Thanks in advance.

1 Answer 1

2

The problem is coming from addGoalHandler

const addGoalHandler = () => {
  let arrGoals = courseGoals;
  arrGoals.push(enteredGoal);
  setCourseGoals(arrGoals);
};

What happened was you are using push method to push it to courseGoals which was mutated the state, one of the option you can do is update to below

const addGoalHandler = () => {
  let arrGoals = [...courseGoals, enteredGoal];
  setCourseGoals(arrGoals);
};

The idea is that, using spread syntax allowing you to create a new copy of array instead of mutated the previous state, and of course it can be shorten down to single line as below

const addGoalHandler = () => setCourseGoals([...courseGoals,enteredGoal])
Sign up to request clarification or add additional context in comments.

3 Comments

I understand that I should not mutate the states of my component, but I am using the push method on an independent variable to save the new "task", and then I am overwriting the data of courseGoals with a new array (like the example you give). for example if I use .concat instead of the push method, it works too. the problem seems to be the .push method. Does React prohibit mutations in any created variable?
I think I got it. the problem is that I am doing .push to a variable that refers to my state, and react does not allow state mutation. but if I do this: let arrGoals = [... courseGoals]; arrGoals.push (enteredGoal); There is no reference to my state, and I only extract its values, the problem is the reference, right? I am right?
@Raphael: Yes you are right, because array and object in JavaScript are shared by reference

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.