Skip to content
Advertisement

onclick changes all mapped items instead of just one

I have a problem where I am trying to click on a certain div being returned by my backend and update it. I am trying to have it setup so that you click edit and the blogTitle and blogBody become input bars where you type in the new title and new body. In my code you can see an update that works and one that does not. The problem with the one that does not is that when I hit edit all blogBody’s and blogTitle’s become input bars instead of just one.

This 5 second of the issue video might make more sense than my explanation.

Now in my code this mainly deals with the following:

<div style={{display : 'flex', flexDirection: 'column-reverse'}}>
    { getBasic.miscData.map(({blogBody, blogTitle, _id}, i) => {
        return(
      <div key={i} >
        <p>{i}</p>
        {prompt ? <p>{blogBody}</p> : <input  onChange={handleChange} name='newerValue' value={Item.newerValue}  placeholder='new title'></input>}
        {prompt ? <p>{blogTitle}</p> : <input  onChange={handleChange} name='newerValue2' value={Item.newerValue2}  placeholder='new title'></input>}
        <p>{blogTitle}</p>
        <p>{_id}</p>

        <button onClick={deleteOne} value={_id}>Delete</button>

        {prompt ? <button onClick={() => { setPrompt(!prompt)}} >Edit</button> : <button onClick={() => { setPrompt(!prompt)}} >Submit</button>}
        
      </div>

Here is the full code:

import './App.css';
import axios from 'axios';
import React, { useState, useEffect } from 'react'

function App() {

  const [getBasic, setGetBasic] = useState()
 
  const [Item, setItem] = useState(
    {
      title: '',
      description: '',
      id: '',
      newValue: '',
      newValue2: '',
      newerValue: '',
      newerValue2: '',
      previousValue: ''
    }
  )

  const [prompt, setPrompt] = useState(true)




  async function fetchData() {
    await axios.get('http://localhost:3001/api')
    .then(result => setGetBasic(result.data))

  }



  function handleChange(event) {
    let {name, value} = event.target;
    setItem(prevInput => {
      return(
        {
          ...prevInput,
          [name]: value,
        }
      );
    });
    // console.log(Item);
  }



  //delete
  function deleteOne(event) {
    event.preventDefault();
    const aValue = event.target.value;
    const deleteItem = {
      // id: Item.id
      id: aValue
    }
    console.log(deleteItem)

    axios.post('http://localhost:3001/api/delete', deleteItem);
    window.location.reload();
    // console.log(deleteItem)

  }


  function updateOne(event) {
    event.preventDefault();
    const updatedItem = {
      previousValue: Item.previousValue,
      newValue: Item.newValue,
      newValue2: Item.newValue2
    }
    console.log(updatedItem)

    axios.put('http://localhost:3001/api/update', updatedItem);
    window.location.reload();
    // console.log(deleteItem)


  }






  useEffect(() => {
    fetchData()
  }, [])

  if (getBasic) {
  
  return (
    <div className="App">
      



      <br />
      {/* A version of update that works */}
      <input  onChange={handleChange} name="previousValue" value={Item.previousValue} placeholder="old value id" />
      <input  onChange={handleChange} name='newValue' value={Item.newValue}  placeholder='new title'></input>
      <input  onChange={handleChange} name='newValue2' value={Item.newValue2}  placeholder='new body'></input>
      <button onClick={updateOne} >update</button>


      {/* A version of update that does not work*/}
    <div style={{display : 'flex', flexDirection: 'column-reverse'}}>
    { getBasic.miscData.map(({blogBody, blogTitle, _id}, i) => {
        return(
      <div key={i} >
        <p>{i}</p>
        {prompt ? <p>{blogBody}</p> : <input  onChange={handleChange} name='newerValue' value={Item.newerValue}  placeholder='new title'></input>}
        {prompt ? <p>{blogTitle}</p> : <input  onChange={handleChange} name='newerValue2' value={Item.newerValue2}  placeholder='new title'></input>}
        <p>{blogTitle}</p>
        <p>{_id}</p>

        <button onClick={deleteOne} value={_id}>Delete</button>

        {prompt ? <button onClick={() => { setPrompt(!prompt)}} >Edit</button> : <button onClick={() => { setPrompt(!prompt)}} >Submit</button>}
        
      </div>
      )})}
      </div>
    
     
    </div>
  )} else {
    return (
      <div>
        <h1>Loading</h1>
        
      </div>
    )
  };
}

export default App;

Now I understand why it is doing this, I just cannot think through the logic of getting my edit button to only edit one at a time. Also I understand the update will not work once I fix this, I am trying to solve this problem of editing 1 at a time first before setting it up how the other update one is.

Edit: so far I received one dislike and no comments I re read through this and realized it lacks a bit of focus thus made the code simpler:

import './App.css';
import axios from 'axios';
import React, { useState, useEffect } from 'react'

function App() {

  const [getBasic, setGetBasic] = useState()
 
  const [Item, setItem] = useState(
    {
      title: '',
      description: '',
      id: '',
      newerValue: '',
      newerValue2: '',
      previousValue: ''
    }
  )

  const [prompt, setPrompt] = useState(true)



  async function fetchData() {
    await axios.get('http://localhost:3001/api')
    .then(result => setGetBasic(result.data))
    console.log(getBasic)
  }



  useEffect(() => {
    fetchData()
  }, [])

  if (getBasic) {
  
  return (
    <div className="App">

    <div style={{display : 'flex', flexDirection: 'column-reverse'}}>
    { getBasic.miscData.map(({blogBody, blogTitle, _id}, i) => {
        return(
      <div key={i} >
        <p>{i}</p>
        {prompt ? <p>{blogBody}</p> : <input  ></input>}
        {prompt ? <p>{blogTitle}</p> : <input ></input>}
        <p>{blogTitle}</p>
        <p>{_id}</p>


        {prompt ? <button onClick={() => { setPrompt(!prompt)}} >Edit</button> : <button onClick={() => { setPrompt(!prompt)}} >Submit</button>}
        
      </div>
      )})}
      </div>
    
     
    </div>
  )} else {
    return (
      <div>
        <h1>Loading</h1>
        
      </div>
    )
  };
}

export default App;

This is all thats needed to work with to solve the issue at hand which is edit one at a time instead of all of them. Leaving the op for reference.

Advertisement

Answer

Have a component for each element so they each have their own unique prompt

For example,

//Element.js

import React from "react";

export default function Element({
  i,
  blogTitle,
  handleChange,
  _id,
  deleteOne,
  blogBody,
  Item
}) {
  const [prompt, setPrompt] = React.useState(true);

  return (
    <div>
      <p>{i}</p>
      {prompt ? (
        <p>{blogBody}</p>
      ) : (
        <input
          onChange={handleChange}
          name="newerValue"
          value={Item.newerValue}
          placeholder="new title"
        ></input>
      )}
      {prompt ? (
        <p>{blogTitle}</p>
      ) : (
        <input
          onChange={handleChange}
          name="newerValue2"
          value={Item.newerValue2}
          placeholder="new title"
        ></input>
      )}
      <p>{blogTitle}</p>
      <p>{_id}</p>

      <button onClick={deleteOne} value={_id}>
        Delete
      </button>

      {prompt ? (
        <button
          onClick={() => {
            setPrompt(!prompt);
          }}
        >
          Edit
        </button>
      ) : (
        <button
          onClick={() => {
            setPrompt(!prompt);
          }}
        >
          Submit
        </button>
      )}
    </div>
  );
}

//App.js

Now in the body return of your main file you could just do this

First import import Element from "./Element"; Then add the new component with specified props

    {getBasic.miscData.map(({ blogBody, blogTitle, _id }, i) => {
        return (
          <Element
            i={i}
            blogTitle={blogTitle}
            handleChange={handleChange}
            _id={_id}
            deleteOne={deleteOne}
            blogBody={blogBody}
            Item={Item}
          />
        );
      })}
User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement