Search code examples
arraysreactjsobjectstatesetstate

ReactJS How to update the state in object which is in the array


Hello I have one problem that I don't know ho to solve.

I have simple formular where the user type som inputs. After that when he clicks on the Button the firstName, lastname and picture will be display under the formular. And when I click on the input it will show the address and date.

But I have problem to do that. In App.js I have a state which initialli si empty array and after click on submit button the user inputs is added to this empty array. In Suggestions.js I map the sugestions array for displaying every suggestion from the user.

In UserInputs.js I have a state where I add into state a 'visible' to false and I want to do, when I clicked on on suggestion in a list it will display the description and date below this particular sugestion.

I want to do it like this. In App.js

const detail = (suggestion) => {
        
        setSuggestions([...suggestions]); //but I don't know how to set state for particular 
                                            suggestion in the array.
      };

My code:

App.js

import React, { useState } from "react";
import Suggestions from "./components/Suggestions";
import UserInputs from "./components/UserInputs";

function App() {
  const [suggestions, setSuggestions] = useState([]);

  const addNewSuggestion = (suggestion) => {
    setSuggestions([suggestion, ...suggestions]);
  };

  const detail = (suggestion) => {
    
    setSuggestions([...suggestions]);
  };

  console.log("suggestions", suggestions);

  return (
    <div className="app-container">
      <UserInputs addNewSuggestion={addNewSuggestion}></UserInputs>
      <Suggestions suggestions={suggestions} detail={detail}></Suggestions>
    </div>
  );
}

export default App;

Suggestions.js

import React from "react";

export default function Suggestions({ suggestions, detail }) {
  return (
    <div className="suggestion-container">
      <h1 className="suggestion-heading">Zoznam Podnetov</h1>
      {suggestions.map((suggestion, index) => {
        return (
          <div
            key={suggestion.id}
            className="suggestion"
            onClick={() => detail(suggestion)}
          >
            <div className="suggestion-number">{index + 1}</div>

            <div className="suggestion-details">
              <div className="suggestion-name">
                {suggestion.firstName}
                {` ${suggestion.lastName}`}
              </div>

              <div className="suggestion-address">{suggestion.address}</div>
              {suggestion.visible ? (
                <div className="suggestion-description">
                  <p>{suggestion.description}</p>
                  <p>Podnet bol pridaný: {suggestion.date}</p>
                </div>
              ) : null}
            </div>

            <div className="suggestion-picture">
              <img
                src={suggestion.picture}
                alt="obrázok"
                className="suggestion-picture"
              ></img>
            </div>
          </div>
        );
      })}
    </div>
  );
}

Userinputs.js

import React, { useState } from "react";

export default function UserInputs({ addNewSuggestion }) {
  const randomId = Math.floor(Math.random() * 1000000);

  const [userInputs, setUserInputs] = useState({
    id: randomId,
    firstName: "",
    lastName: "",
    address: "",
    description: "",
    picture: null,
    date: new Date().toLocaleDateString(),
    visible: true,
  });

  const onInputChange = (event) => {
    setUserInputs({
      ...userInputs,
      [event.target.name]: event.target.value,
    });
  };

  const fileSelectHandler = (event) => {
    setUserInputs({
      ...userInputs,
      picture: URL.createObjectURL(event.target.files[0]),
    });
  };

  const onSubmit = (event) => {
    event.preventDefault();

    addNewSuggestion(userInputs);

    setUserInputs({
      id: randomId,
      firstName: "",
      lastName: "",
      address: "",
      description: "",
      picture: null,
      date: new Date().toLocaleDateString(),
      visible: true,
    });
  };

  return (
    <div>
      <form className="form-container">
        <div className="row">
          <label>Meno</label>
          <input
            autoFocus
            type="text"
            name="firstName"
            value={userInputs.firstName}
            onChange={onInputChange}
          ></input>
        </div>

        <div className="row">
          <label>Priezvisko</label>
          <input
            type="text"
            name="lastName"
            value={userInputs.lastName}
            onChange={onInputChange}
          ></input>
        </div>

        <div className="row">
          <label>Adresa</label>
          <input
            type="text"
            name="address"
            value={userInputs.address}
            onChange={onInputChange}
          ></input>
        </div>

        <div className="row">
          <label>Popis</label>
          <input
            type="text"
            name="description"
            value={userInputs.description}
            onChange={onInputChange}
          ></input>
        </div>

        <div className="row">
          <input type="file" onChange={fileSelectHandler}></input>
        </div>

        <button onClick={onSubmit} className="button">
          Odoslať
        </button>
      </form>
    </div>
  );
}

Thank you very much for your help.


Solution

  • you can update the suggestion, where the id matches input suggestion and only update it. Please find the code below:

    const detail = (suggestion) => { 
    
      let tempSuggestions = suggestions.map( (item) => {  
      if(item.id === suggestion.id) return suggestion
      return item
    })
            
    setSuggestions([...tempSuggestions]);                                            
    }