0

I am having a state data. I wanted to push a new entry of the form

{  task:'ANy task',key:Math.random().toString() }

in the data array while using setData.

I had tried many ways mentioned here, but don't klnow why its not working.

Here's my code.

import React, { useState } from "react";
import { StyleSheet, Text, View, TextInput, Button } from "react-native";
import { StatusBar } from "expo-status-bar";

const Addtask = ({navigation}) => {
 
  const [data,setData] = useState([]);

  console.log("from add = ",data)

  const [task, setTask] = useState("");


  const handleSubmit = () => {
    console.log("submit pressed for task = ", task)
    

    const updatedData = [...data,{
      task:task,
      key: Math.random().toString(),
    }]
    //here i am setting the data
    setData(prevState => [...prevState,updatedData]);
    console.log("data after adding task",data)
    
    navigation.navigate("Tasklist",{data:data})
  }

  return (
    <View style={styles.container}>
      <StatusBar style="light" backgroundColor="midnightblue" />
      <View>
        <Text style={styles.text}>Add Task Here</Text>
      </View>

      <View>
        <TextInput
          style={styles.input}
          onChangeText={setTask}
          value={task}
          onChange={setTask}
          placeholder="Type your task"
          keyboardType="ascii-capable"
        />
      </View>

      <View style={styles.buttoms}>
        <View style={{margin:4}}>
          <Button color={'red'} onPress={()=>{navigation.goBack()}} title="Cancel"></Button>
        </View>
        <View style={{margin:4}}>
          <Button color={'lightblue'} onPress={()=>setTask('')} title="Clear"></Button>
        </View>
        <View style={{margin:4}}>
          <Button color={'green'} onPress={handleSubmit} title="Save"></Button>
        </View>
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  .
  .
  .
});
export default Addtask;

To debug, I had used console stmts which reveals that the task value is coming in the handleSubmit() correctly but it is not getting pushed.

Log

submit pressed for task =  Morning bike ride.
data after adding task Array []
MagnusEffect
  • 3,363
  • 1
  • 16
  • 41
  • You haven't followed the example correctly from the link you've shared. `updatedData` is your new state value that you want to set `data` to, it doesn't make much sense to then add that again to the end of your current state array with `[...prevState,updatedData]`. Logging `data` directly after you call `setData()` won't show the changed data value, as the new data value is only available in the next render. You can use `setData(updatedData)`, and refer to `updatedData` instead of `data` when you call `navigate()` – Nick Parsons Jun 12 '22 at 03:01
  • But in this way if I pass `updatedData`, then only the most recent value will be passed, not all the values. I just want to push the `task` value into the array `data` every time. – MagnusEffect Jun 12 '22 at 11:13
  • I instead defined `let data = [ ]`, instead of state and then pushing data using data.push({....}), and its working. But I wonder then what is the use of `states` with array-type in reactjs?? – MagnusEffect Jun 12 '22 at 11:20
  • Most of the time, accessing `data` directly within `onSubmit` will refer to your latest state value. It is only if that state value is updated more than once before the next render occurs will it not be the current state, thus requiring the state setter function. The purpose of keeping your `data` array in state is so that your UI will re-render when you update it. Using `.push()` won't make your UI update whn you change `data`. Moreover, `data` will be redeclared as an empty array each re-render if you have defined `let data = [];` within your component. – Nick Parsons Jun 12 '22 at 11:28
  • If you have defined `data` outside of your component, then you'll face issues if you try and use this component in two places. If you need changes to `data` to be reflected in your UI, then you would use state, otherwise, if you just need a persistent variable that doesn't get reflected in your UI, then you would use a ref: `useRef()` – Nick Parsons Jun 12 '22 at 11:31
  • Yes you are correct, now I am facing the same problem. When I entrered my app, it first goes to the screen showing the tasks, but now `data` is undefined and as soon as I goto next screen, then it Appears the tasks list in the console. – MagnusEffect Jun 12 '22 at 11:37
  • Which means that when you click on app, you will see nothing on tasklist page, then you add a task by pressing a button below, which navigate to you to the next screen where you input your task and save, if there are already values in `data`, then suddenly all the previous values along with the new task value will appear in the tasklist screen , which is awful. – MagnusEffect Jun 12 '22 at 11:39
  • 1
    Sounds like you need to lift your state up that contains your list of tasks to a parent component so that both `Addtask` and your `Tasklist` components update the same state. This can either be done by making `AddTask` and `TaskList` children of the same parent component, where this parent component keeps the state for your task list. Or, you can make `AddTask` a child of `TaskList`, and keep the state of your task list in `TaskList`, then pass through the state setter function to `AddTask` when you want to update your state. Otherwise, you can use `useContext()` if needed – Nick Parsons Jun 12 '22 at 11:51

1 Answers1

0

Because You are already have

const updatedData = [...data,{
  task:task,
  key: Math.random().toString(),
}]

You don't need setData(prevState => [...prevState,updatedData]) you can just assign the updatedData to setData like setData(updatedData)

You can use

setData(current => [...current, {
  task:task,
  key: Math.random().toString(),
}])

Then you don't need updatedData

MH Sagar
  • 136
  • 2
  • 11
  • This is not working man, same problem appearing – MagnusEffect Jun 12 '22 at 11:09
  • I instead defined let data = [ ], instead of state and then pushing data using data.push({....}), and its working. But I wonder then what is the use of states with array-type in reactjs?? – MagnusEffect Jun 12 '22 at 11:20
  • In reactjs state is just a object that stores data which might get updated and also will be shared in any component of your project. Like all object it can hold all type of data array too. if you think using data.push() is an extra step then you can always use setData(current => [...current, { task:task, key: Math.random().toString(), }]) – MH Sagar Jun 15 '22 at 03:03