By using this site, you agree to the Privacy Policy and Terms of Use.
Accept
rocoderesrocoderes
  • Home
  • HTML & CSS
    • Login and Registration Form
    • Card Design
    • Loader
  • JavaScript
  • Python
  • Internet
  • Landing Pages
  • Tools
    • Google Drive Direct Download Link Generator
    • Word Count
  • Games
    • House Painter
Notification Show More
Latest News
How to set the dropdown value by clicking on a table row
Javascript – How to set the dropdown value by clicking on a table row
JavaScript
Attempting to increase the counter, when the object's tag exist
Javascript – Attempting to increase the counter, when the object’s tag exist
JavaScript
Cycle2 JS center active slide
Javascript – Cycle2 JS center active slide
JavaScript
Can import all THREE.js post processing modules as ES6 modules except OutputPass
Javascript – Can import all THREE.js post processing modules as ES6 modules except OutputPass
JavaScript
How to return closest match for an array in Google Sheets Appscript
Javascript – How to return closest match for an array in Google Sheets Appscript
JavaScript
Aa
Aa
rocoderesrocoderes
Search
  • Home
  • HTML & CSS
    • Login and Registration Form
    • Card Design
    • Loader
  • JavaScript
  • Python
  • Internet
  • Landing Pages
  • Tools
    • Google Drive Direct Download Link Generator
    • Word Count
  • Games
    • House Painter
Follow US
High Quality Design Resources for Free.
rocoderes > JavaScript > Javascript – Why does my click event require two clicks (react)
JavaScript

Javascript – Why does my click event require two clicks (react)

Admin
Last updated: 2023/12/24 at 1:53 PM
Admin
Share
5 Min Read
Why does my click event require two clicks (react)

Problem:

I’ve seen some solutions for other frameworks but none apply to me. I have two main issues here.

Contents
Problem:Solution:

1- I have to click the button twice to get it to fire. Granted I am using the click even’t to mutate the state, change the row color, AND also update a list on the bottom of the table. I don’t think none of these are running asynchronously. So maybe that’s the problem and I would like to know how to go around that.

2- Second problem is related to the first. I passed the dependency in the useEffect function so that the list on the bottom is updated as soon as the click event changes the state. But it’s throwing an infinite loop, as if the state was constantly changing. A console log doesn’t reflect the state forever changing. So, I’m stooped.

Some basically I have an array (API in real world), and I’m filtering out the learned and unlearned questions

const questions = [
  { 
    question: "Question 1",
    answer: "My answer 1",
    learned: true
  },
  {
    question: "Question 2",
    answer: "My answer 2",
    learned: false
  },
  {
    question: "Question 3",
    answer: "My answer 3",
    learned: true
  },
  {
    question: "Question 4",
    answer: "My answer 4",
    learned: true
  },
  {
    question: "Question 5",
    answer: "My answer 5",
    learned: false
  },
  {
    question: "Question 6",
    answer: "My answer 6",
    learned: true
  }
]

const learned = questions.filter(question => question.learned === true)
const unlearned = questions.filter(question => question.learned === false)

Inside my component I have the state, the function to populate a list, useEffect, and a click event function that contains the callback to populate the list, as well as toggling the UI from learned to unlearned, which of course, it updates the list accordingly

const [unlearned, setUnlearned] = useState([]);

const populateUnlearned = () => {
  setUnlearned(questions.filter(question => question.learned === false))
}

useEffect(() => {
  populateUnlearned()
},[]) //unlearned here causes the list to populate fine but an infinite loop

const handleLearned = (index) => {  
  populateUnlearned()
  setIsLearned(
    !isLearned, 
    questions.filter(question => question.learned === false), 
    questions[index].learned = !isLearned
  )
}

And the rest is just html stuff. I have a sandbox here for you to mess with showing the problem.

I appreciate any help. Thanks in advance

Solution:

here are a few updates I would recommend,

  1. State variables

In Vocabulary.js, you attempt to modify the entries in questions. However, this variable is not a piece of state. Keep in mind that only variables created based on useState (and useReducer) can be updated within your component

  1. Avoid performing updates based on index

here you can find information that explains in detail why you should not be using the index

// rename questions to original_questions
const original_questions = [
 {
  ...

// compute them within the component
//const learned = questions.filter((question) => question.learned === true);
//const unlearned = questions.filter((question) => question.learned === false);
const Vocabulary = () => {
  const [page, setPage] = useState(0);
  const [rowsPerPage, setRowsPerPage] = useState(5);

  // unneeded since each entry in "questions" keeps track that flag
  // const [isLearned, setIsLearned] = useState(false);

  // questions get initiated as a piece of state
  // based on the original_questions (this can be a prop)
  const [questions, setQuestions] = useState(original_questions);
  const [unlearned, setUnlearned] = useState([]);

  // effects computes unlearned
  // whenever questions state changes
  useEffect(() => {
    populateUnlearned();
  }, [questions]);

  // other functions...
  

  // instead of index,
  // handleLearned expects the row data 
  // (ideally row should have a unique id e.g row.id)
  // the update uses the `question` property to uniquely identify
  // the question to update 
  const handleLearned = (row) => {
    setQuestions((currentQuestions) =>
      currentQuestions.map((entry) => {
        if (row.question === entry.question) { 
          entry.learned = !entry.learned;
        }
        return entry;
      })
    );
    //populateUnlearned();
    //setIsLearned(
    //  !isLearned,
    //  questions.filter((question) => question.learned === false),
    //  (questions[index].learned = !isLearned)
    //);
    // setUnlearned(questions.filter(question => question.learned === false))
    // questions[index].learned = !isLearned
  };


  // more code ...
  // button onClick callback now gets the row instead of index
  <StyledTableCell align="center">
                  <Button
                    onClick={() => handleLearned(row)} 
                    variant="contained"
                    color={row.learned ? "error" : "success"}
                    size="small"
                    sx={{ mr: 2 }}
                  >
                    {row.learned ? "No" : "Yes"}
                  </Button>
                </StyledTableCell>

Related

Subscribe to Our Newsletter

Subscribe to our newsletter to get our newest articles instantly!

Share this Article
Facebook Twitter Email Print
What do you think?
Love0
Sad0
Happy0
Sleepy0
Angry0
Dead0
Wink0
Previous Article close dropdown for input-"search" on -webikit-search-cancel-button click Javascript – close dropdown for input-“search” on -webikit-search-cancel-button click
Next Article Blazor: Removing an element from c# code works only once, then resets the connection Javascript – Blazor: Removing an element from c# code works only once, then resets the connection
Leave a comment Leave a comment

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

- Advertisement -

You Might Also Like

How to set the dropdown value by clicking on a table row

Javascript – How to set the dropdown value by clicking on a table row

February 11, 2024
Attempting to increase the counter, when the object's tag exist

Javascript – Attempting to increase the counter, when the object’s tag exist

February 11, 2024
Cycle2 JS center active slide

Javascript – Cycle2 JS center active slide

February 10, 2024
Can import all THREE.js post processing modules as ES6 modules except OutputPass

Javascript – Can import all THREE.js post processing modules as ES6 modules except OutputPass

February 10, 2024
rocoderesrocoderes
Follow US

Copyright © 2022 All Right Reserved By Rocoderes

  • Home
  • About us
  • Contact us
  • Disclaimer
Join Us!

Subscribe to our newsletter and never miss our latest news, podcasts etc.

Zero spam, Unsubscribe at any time.
Welcome Back!

Sign in to your account

Lost your password?