Home > Blockchain >  OnClick Saving Only One ID at a time on UseState Array - ReactJS
OnClick Saving Only One ID at a time on UseState Array - ReactJS

Time:06-16

i am trying to save favorite post ids in an array with button click. The thing is currently it is only saving one ID at a time in array and when you click you on another "click here" button , it removes the previous id and show you the current id. Currently my array is not saving previous saved Ids with the new one. I will appreciate it if someone explain why it is not working and is there something wrong in my code while saving the ids.

Screenshot

enter image description here

Code

import React, { useEffect } from 'react'
import Demopic from "../assets/img/demopic/4.jpg";
import { useState, useRef } from 'react';
import { post } from 'jquery';

export default function Post(props) {
    
  const { id, title, body } = props.data;

  const [postid,setPostID] = useState([]);
  const [isActive, setActive] = useState(false);  

  

  function onHandleOnClick(id) {

    setPostID([...postid, id]);
    
  };
  useEffect(()=>{
    console.log(postid);
  },[postid]);


  return (
    
            
    <div className="card">
        <div className="row">
            <div className="col-md-5 wrapthumbnail">
                <a href="post.html">
                    <div className="thumbnail dd" style={{ backgroundImage: 'url('   Demopic   ')' }}>
                    </div>
                </a>
            </div>
            <div className="col-md-7">
                <div className="card-block">
                    <h2 className="card-title"><a href={'/post-detail/' id} key={id}>{title}</a></h2>
                    
                    <h4 className="card-text">
                    {body.length > 100 ? `${body.substring(0, 90)}...` : body }
                    </h4>
                    <div className="metafooter">
                        <div className="wrapfooter text-left">
                            <span className="meta-footer-thumb">
                            <a href="author.html">
                                <img className="author-thumb" src="https://www.gravatar.com/avatar/e56154546cf4be74e393c62d1ae9f9d4?s=250&amp;d=mm&amp;r=x" alt="Sal"/></a>
                            </span>
                            <span className="author-meta">
                            <span className="post-name"><a href="author.html">Steve</a></span><br/>
                            <span className="post-date">22 July 2017</span><span className="dot"></span><span className="post-read">6 min read</span>
                            </span>
                            <button onClick={(e)=>onHandleOnClick(id)} value={id}>click here</button>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
            
       
  )
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

CodePudding user response:

looks like your Post component is a single post, therefore each one of the Post components that you are creating will have their own postId array.

so if you have 10 posts you will have 10 different arrays, to test this, you can click on the same button multiple times and you will see that they array of that component will grow, for example the Id is 4 and you click multiple times you will see [4 ,4, 4, 4.....] and then if you do it on the Id 2 you will see [2, 2, 2, 2....].

to fix this you should have on your parent component the array and then in then pass the update function to your childs, something like this:

const ParentComponent = () => {
const [postid,setPostID] = useState([]);
  const [isActive, setActive] = useState(false);  

  function onHandleOnClick(id) {
    setPostID([...postid, id]);
  };

  useEffect(()=>{
    console.log(postid);
  },[postid]);


  return (<>
         <Post clickFavourite={onHandleOnClick}  ...other props/>
         <Post clickFavourite={onHandleOnClick}  ...other props/>
         <Post clickFavourite={onHandleOnClick}  ...other props/>
         <Post clickFavourite={onHandleOnClick}  ...other props/>
         <Post clickFavourite={onHandleOnClick}  ...other props/>
         </>)
}

and then in your child component (Post) you should remove the state and the handler and just use the parent function:

function Post(props) {
    
  const { id, title, body } = props.data;
  const { clickFavourite } = props;

  return (
    <button onClick={(e)=>clickFavourite(id)} value={id}>click here</button>
  )
}

notice that I deleted a lot of the content of the Post component just to read it easily.

also take into account that this can be done in different ways, this was the first way that came into my mind but you can use global states, states managers, hooks, etc etc. but as far as I see this is the easiest way and will get the job done

CodePudding user response:

Use

const [postid,setPostID] = useState({});

Instead of

   const [postid,setPostID] = useState([]); 

It will work.

  • Related