简体   繁体   中英

react setstate change object inside array of object of array

i have a problem with react i need to setstate a spesific user when i click at button "succeed" it will change the object inside to false this is the deatils first i have an array of object (users) and object that called "workoutDeatils" inside this object i have 3 object the last one on index 2 is called "workout" inside this workout i have a object of all the workout and i need to change it spesific the problem when i want to use the setstate of users on the change it dosent work (because it gets confused) what i need to do is: change status to false this one i know but how i will setstate the users with the map? it should be nasted loop?

import HomePage from "./componente/HomePage";
import React, { useState } from "react";
import WorkoutDeatilsField from "./componente/WorkoutDeatilsField";
import SpesificUser from "./componente/SpesificUser";
import Workout from "./componente/Workout";
import { BrowserRouter, Route, Routes } from "react-router-dom";
function App() {
  const [users, setUsers] = useState([]);
  const [spesificUserId, setSpesificUserId] = useState(0);
  const [spesificWorkOut, setSpesificWorkout] = useState();
  const spesificUser = users.find((user) => {
    return user.id == spesificUserId;
  });
  const getWorkoutDeatils = () => {
    const { workout } = spesificUser.workoutDeatils[2];
    const spesificWorkoutPlane = workout.find((workout) => {
      return workout.workoutNum == spesificWorkOut;
    });
    return spesificWorkoutPlane;
  };

  const findUserExists = (id) => {
    const checkUserExists = users.filter((user) => {
      return user.id == id;
    });

    return checkUserExists.length !== 0 ? true : false;
  };

  const addUser = (id, fullName, gender) => {
    const user = {
      id: id,
      fullName: fullName,
      gender: gender,
    };

    setUsers((prev) => {
      return [...prev, user];
    });
  };
  const setTraning = (trainWeek, trainInYears) => {
    const workoutInWeeks = new Array(Number(trainWeek)).fill(1);
    let kmcacluator = (trainInYears * 5) / trainWeek;

    const workoutDeatils = [
      {
        trainWeek: Number(trainWeek),
      },
      { trainYears: Number(trainInYears) },
      {
        workout: workoutInWeeks.map((workout, index) => {
          kmcacluator = kmcacluator + (kmcacluator / 100) * 15;
          return { workoutNum: index + 1, km: Math.ceil(kmcacluator), status: true };
        }),
      },
    ];

    const afterMap = users.map((user) => {
      return user.id == spesificUserId ? { ...user, workoutDeatils } : { ...user };
    });
    setUsers(afterMap);
  };
const get = ()=>{
  const afterMap = users.map((user)=>{
  })
}
  return (
    <div className="App">
      <BrowserRouter>
        <Routes>
          <Route
            path="/"
            element={
              <HomePage findUserExists={findUserExists} addUser={addUser} setSpesificUserId={setSpesificUserId} />
            }
          ></Route>
          <Route
            path="/workoutdeatilsfield"
            element={<WorkoutDeatilsField spesificUser={spesificUser} setTraning={setTraning} />}
          ></Route>
          <Route
            path="/traning/:id"
            element={<SpesificUser setSpesificWorkout={setSpesificWorkout} spesificUser={spesificUser} />}
          ></Route>
          <Route path="/workout" element={<Workout getWorkoutDeatils={getWorkoutDeatils} />}></Route>
        </Routes>
      </BrowserRouter>

      <button
        onClick={() => {
          console.log(users);
        }}
      >
        Click
      </button>
    </div>
  );
}

export default App;



{
    "id": "1",
    "fullName": "dsa",
    "gender": "male",
    "workoutDeatils": [
        {
            "trainWeek": 3
        },
        {
            "trainYears": 2
        },
        {
            "workout": [
                {
                    "workoutNum": 1,
                    "km": 4,
                    "status": true
                },
                {
                    "workoutNum": 2,
                    "km": 5,
                    "status": true
                },
                {
                    "workoutNum": 3,
                    "km": 6,
                    "status": true
                }
            ]
        }
    ]
}

this is an example how it add user with his deatils

React's setState doesn't re-render the component if the state does not change. "state change" means you call setState with a value different from the previous one. "different" means it is not strictly equal ( === ) to the previous one. In JavaScript objects are compared by reference, so in order to change an object with setState you have to set a new object .

Thankfully, setState can receive a function that takes the previous states and computates the next one, particularlly useful for your use case when you want to update a nested property of an object. The key here is that you have to declare a new object and put all the data of the old object into the new one, changing only the value you want to change. With some spreading ( ... ) and array methods ( filter , find ) you can easily, for example, toggle the status of the third wourkout.

    const workoutNum = 3 // Or whatever workout you want to change
    
    setUser(previous => {
      const workoutToChange = previous.workoutDetails[2].workout
        .find(d => d.workoutNum === workoutNum)
    
      return {
        ...previous,
        workoutDetails: [
          ...previous.workoutDetails.filter(details => !details.workout),
          { workout: [
            ...previous.workoutDetails[2].filter(w => w.workountNum !== workoutNum),
            { ...workoutToChange, status: !workoutToChange.status }
          ]}
        ]
      }
    })

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM