Trying to mutate the state of React component - javascript

I'm trying to create a quizz app and got stuck at the moment when I need to change the background of the Answers (button) when the user clicked on it. Well, function holdAnswer does console.log the id of the answer, but doesn't change its background. What's missing here?
I assume I have also stored all answers that the user chose in some array in order to count how many answers the user guessed.
After I check if the answers are correct or not they have to be highlighted accordingly (correct/incorrect), so again it needs to mutate the state.
Is the code missing something from the beginning?
here is CodeSandBox link
App.js
import { useState } from "react";
import QuestionSet from "./QuestionSet";
import Answers from "./Answers";
import { nanoid } from "nanoid";
function App() {
const [isQuesLoaded, setIsQuesLoaded] = useState(false);
const [questions, setQuestions] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
async function startQuiz() {
try {
setIsQuesLoaded(!isQuesLoaded);
const response = await fetch(
"https://opentdb.com/api.php?amount=5&category=12&difficulty=easy&type=multiple"
);
const data = await response.json();
const allQuestions = data.results;
const listOfQuestions = allQuestions.map((item) => {
const allAnswers = [
{
id: nanoid(),
isCorrect: false,
isChosen: false,
answer: item.incorrect_answers[0],
},
{
id: nanoid(),
isCorrect: false,
isChosen: false,
answer: item.incorrect_answers[1],
},
{
id: nanoid(),
isCorrect: false,
isChosen: false,
answer: item.incorrect_answers[2],
},
{
id: nanoid(),
isCorrect: true,
isChosen: false,
answer: item.correct_answer,
},
];
return {
id: nanoid(),
question: item.question,
answers: allAnswers,
};
});
setQuestions(listOfQuestions);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
}
function holdAnswer(id) {
console.log(id);
setQuestions((prevQuestion) =>
prevQuestion.map((question) =>
question.answers.id === id
? {
...question,
answers: question.answers.map((answer) =>
answer.id === id
? { ...answer, isChosen: !answer.isChosen }
: answer
),
}
: question
)
);
}
const questionElm = questions.map((question, index) => {
return (
<section key={index}>
<QuestionSet question={question.question} key={question.id} />
<Answers
answers={question.answers}
isChosen={question.answers.isChosen}
holdAnswer={holdAnswer}
/>
</section>
);
});
return (
<div className="App">
{!isQuesLoaded ? (
<main>
<h1 className="title-app">Quizzical</h1>
<p className="desc-app">Some description if needed</p>
<button className="btn" onClick={startQuiz}>
Start Quiz
</button>
</main>
) : (
<main className="quest-box">
{loading && <div>Loading data...</div>}
{error && <div>{`There is a problem fetchning data = ${error}`}</div>}
<section className="quest-content">{questionElm}</section>
<button className="answer-btn">Check Answers</button>
</main>
)}
</div>
);
}
export default App;
Answers.js
export default function Answers(props) {
const styles = {
backgroundColor: props.answers.isChosen ? "#D6DBF5" : "transparent",
};
return (
<section className="answer-container">
<div
className="answer-div"
style={styles}
id={props.answers[3].id}
onClick={() => props.holdAnswer(props.answers[3].id)}
>
<p>{props.answers[3].answer}</p>
</div>
<div
className="answer-div"
style={styles}
id={props.answers[1].id}
onClick={() => props.holdAnswer(props.answers[1].id)}
>
<p>{props.answers[1].answer}</p>
</div>
<div
className="answer-div"
style={styles}
id={props.answers[2].id}
onClick={() => props.holdAnswer(props.answers[2].id)}
>
<p>{props.answers[2].answer}</p>
</div>
<div
className="answer-div"
style={styles}
id={props.answers[0].id}
onClick={() => props.holdAnswer(props.answers[0].id)}
>
<p>{props.answers[0].answer}</p>
</div>
</section>
);
}

Your making confusions on object fields, using typescript will prevent you from doing this kind of error.
function holdAnswer(id) {
console.log(id);
setQuestions((prevQuestion) =>
prevQuestion.map((question) =>
question.answers.id === id // question.answers is an array
// you need to pass the questionId to holdAnswer and use it here
? {
...question,
answers: question.answers.map((answer) =>
answer.id === id
? { ...answer, isChosen: !answer.isChosen }
: answer
)
}
: question
)
);
}
// props.answers is also an array, create a component for Answer and use style here
const styles = {
backgroundColor: props.answers.isChosen ? "#D6DBF5" : "transparent"
};
Here is the codesandbox if you want to see how to fix it.

I wont give any direct answer, its up to you to find out.
First, there is an issue with the React.StrictMode as it runs some of the react api twice such as useEffect (and in ur case the setter for setQuestions), you can remove it for now since i dont think you really need it for this.
Lastly, if you look carefully at where you are changing the styles conditionally you'll see that you are referencing some object fields incorrectly.
it looks like you're just starting out react, so good luck and happy coding.

Related

Getting first values from objects instead of getting that was chosen by user

Function holdAnswer has to change the property isChosen from false to true and mutate state, adding new value to the questions. Then function checkAnswers has to find answers that user has chosen and compare if the selected answers have property isCorrect, which has to be true. And if isCorrect is true and isChosen is true, function checkAnswers has to change the score count. It keeps showing me only the first answers, no matter what the user chose. Why it doesn't show me the answers which user chose?
Please take a look at Codesandbox
App.js
import { useState } from "react";
import QuestionSet from "./components/QuestionSet";
import Answers from "./components/Answers";
import { nanoid } from "nanoid";
function App() {
const [isQuesLoaded, setIsQuesLoaded] = useState(false);
const [questions, setQuestions] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const [score, setScore] = useState(0);
async function startQuiz() {
try {
setIsQuesLoaded(!isQuesLoaded);
const response = await fetch(
"https://opentdb.com/api.php?amount=5&category=12&difficulty=easy&type=multiple"
);
const data = await response.json();
const allQuestions = data.results;
const listOfQuestions = allQuestions.map((item) => {
const allAnswers = [
{
id: nanoid(),
isCorrect: false,
isChosen: false,
answer: item.incorrect_answers[0]
},
{
id: nanoid(),
isCorrect: false,
isChosen: false,
answer: item.incorrect_answers[1]
},
{
id: nanoid(),
isCorrect: false,
isChosen: false,
answer: item.incorrect_answers[2]
},
{
id: nanoid(),
isCorrect: true,
isChosen: false,
answer: item.correct_answer
}
];
return {
id: nanoid(),
question: item.question,
answers: allAnswers
};
});
setQuestions(listOfQuestions);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
}
function holdAnswer(questionId, answerId) {
console.log({ questionId, answerId });
setQuestions((prevQuestion) =>
prevQuestion.map((question) =>
question.id === questionId
? {
...question,
answers: question.answers.map((answer) =>
answer.id === answerId
? { ...answer, isChosen: !answer.isChosen }
: answer
)
}
: question
)
);
}
function checkAnswers() {
let correctCount = 0;
questions.forEach(question => {
const selectedAnswer = question.answers.find(answer => answer.answer.id === answer.answer.isChosen);
if (selectedAnswer.isCorrect) correctCount += 1;
setScore(correctCount);
console.log(correctCount);
console.log(selectedAnswer);
})
}
const questionElm = questions.map((question, index) => {
return (
<section key={index}>
<QuestionSet question={question.question} key={question.id} />
<Answers
answers={question.answers}
isChosen={question.answers.isChosen}
holdAnswer={(answerId) => holdAnswer(question.id, answerId)}
/>
</section>
);
});
return (
<div className="App">
{!isQuesLoaded ? (
<main>
<h1 className="title-app">Quizzical</h1>
<p className="desc-app">Some description if needed</p>
<button className="btn" onClick={startQuiz}>
Start Quiz
</button>
</main>
) : (
<main className="quest-box">
{loading && <div>Loading data...</div>}
{error && <div>{`There is a problem fetchning data = ${error}`}</div>}
<section className="quest-content">{questionElm}</section>
<button className="answer-btn" onClick={checkAnswers}>Check Answers</button>
</main>
)}
</div>
);
}
export default App;
Answers.js
function Answer(props) {
const styles = {
backgroundColor: props.answer.isChosen ? "#D6DBF5" : "transparent"
};
return (
<div
className="answer-div"
style={styles}
id={props.answer.id}
onClick={() => props.holdAnswer(props.answer.id)}
>
<p>{props.answer.answer}</p>
</div>
);
}
export default function Answers(props) {
return (
<section className="answer-container">
{props.answers.map((answer) => (
<Answer holdAnswer={props.holdAnswer} answer={answer} key={answer.id} />
))}
</section>
);
}
QuestionSet.js
export default function QuestionSet(props) {
return (
<section className="quest" key={props.id}>
<p>{props.question}</p>
</section>
);
}
First thing that I'm seeing is that you are passing holdAnswer function down via props on a wrong way
You need to change to something this (Simplified for convenience):
App.js
<Answers
answers={question.answers}
isChosen={question.answers.isChosen}
holdAnswer={
holdAnswer(question.id, answerId) // Telling what to execute from here (Without the param on the arrow function)
}
/>
Answers.js
<Answer holdAnswer={
props.holdAnswer // passing the whole function knowing what to execute
}
/>
Answer
<button onClick={() =>
props.holdAnswer // knowing what to do from App.js
}
/>
Or you can do it like this:
App.js
<Answers
answers={question.answers}
isChosen={question.answers.isChosen}
holdAnswer={
holdAnswer // passing the whole function to execute it in another component
}
/>
Answers.js
<Answer holdAnswer={
props.holdAnswer // passing the whole function to execute it in another
}
/>
Answer
<button onClick={() =>
props.holdAnswer(props.param1, props.param2) // executing the function here passing the parameters
}
/>
Not sure if this is going to fix your problem but at least it can simplify it.

Get undefined value from props on onClick event meanwhile the whole props are displaying well

I'm stuck getting undefined value when clicking on Answers "buttons". It has to console.log the id of this button which was generated by nanoid().
Questions.js
import { useState, useEffect } from "react";
import { nanoid } from "nanoid";
import QuestionSet from "./QuestionSet";
import Answers from "./Answers";
export default function Questions() {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetch(
"https://opentdb.com/api.php?amount=5&category=12&difficulty=easy&type=multiple"
)
.then((response) => {
if (!response.ok) {
throw new Error(
`This is an HTTP error: The status is ${response.status}`
);
}
return response.json();
})
.then((actualData) => {
setData(actualData.results);
setError(null);
})
.catch((err) => {
setError(err.message);
setData(null);
})
.finally(() => {
setLoading(false);
});
}, []);
const listOfQuestions = data.map((item) => {
const allAnswers = [
{ id: nanoid(), isCorrect: false, answer: item.incorrect_answers[0] },
{ id: nanoid(), isCorrect: false, answer: item.incorrect_answers[1] },
{ id: nanoid(), isCorrect: false, answer: item.incorrect_answers[2] },
{ id: nanoid(), isCorrect: true, answer: item.correct_answer },
];
return {
id: nanoid(),
question: item.question,
answers: allAnswers,
};
});
function holdAnswer(id) {
console.log(id);
}
const questionElm = listOfQuestions.map((question, index, i) => {
return (
<section key={index}>
<QuestionSet question={question.question} key={question.id} />
<Answers
answers={question.answers}
isChosen={question.isChosen}
id={question.answers.id}
holdAnswer={() => holdAnswer(question.answers.id)}
/>
</section>
);
});
return (
<main className="quest-box">
<section className="quest-content">{questionElm}</section>
<button className="answer-btn">Check Answers</button>
{loading && <div>Loading data...</div>}
{error && <div>{`There is a problem fetchning data = ${error}`}</div>}
</main>
);
}
QuestionSet.js (component)
export default function QuestionSet(props) {
return (
<section className="quest" key={props.id}>
<p>{props.question}</p>
</section>
);
}
Answers.js (component)
export default function Answers(props) {
const styles = {
backgroundColor: props.isChosen ? "#D6DBF5" : "transparent",
};
return (
<section className="answer-container">
<div
className="answer-div"
style={styles}
id={props.answers[3].id}
onClick={props.holdAnswer}
>
<p>{props.answers[3].answer}</p>
</div>
<div
className="answer-div"
style={styles}
id={props.answers[1].id}
onClick={props.holdAnswer}
>
<p>{props.answers[1].answer}</p>
</div>
<div
className="answer-div"
style={styles}
id={props.answers[2].id}
onClick={props.holdAnswer}
>
<p>{props.answers[2].answer}</p>
</div>
<div
className="answer-div"
style={styles}
id={props.answers[0].id}
onClick={props.holdAnswer}
>
<p>{props.answers[0].answer}</p>
</div>
</section>
);
}
Other props are displayed well such as questions and answer text. Also, I tested if the id of questions will be displaying and it works, but not the ids of the answers.
Why does it happen? Why does the part of allAnswers array are showing but the part with ids doesn't? :(
You are doing a few things wrong.
There is no question.answers.id it is an array, what you want is question.answers[0].id
Even with 1 sorted out, the way you handle the click is wrong, you need to just pass the function down to the child component, and let the child component handle it by itself
This is how your code will look like
Questions.js
import { useState, useEffect } from "react";
import { nanoid } from "nanoid";
import QuestionSet from "./QuestionSet";
import Answers from "./Answers";
export default function Questions() {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetch(
"https://opentdb.com/api.php?amount=5&category=12&difficulty=easy&type=multiple"
)
.then((response) => {
if (!response.ok) {
throw new Error(
`This is an HTTP error: The status is ${response.status}`
);
}
return response.json();
})
.then((actualData) => {
setData(actualData.results);
setError(null);
})
.catch((err) => {
setError(err.message);
setData(null);
})
.finally(() => {
setLoading(false);
});
}, []);
const listOfQuestions = data.map((item) => {
const allAnswers = [
{ id: nanoid(), isCorrect: false, answer: item.incorrect_answers[0] },
{ id: nanoid(), isCorrect: false, answer: item.incorrect_answers[1] },
{ id: nanoid(), isCorrect: false, answer: item.incorrect_answers[2] },
{ id: nanoid(), isCorrect: true, answer: item.correct_answer }
];
return {
id: nanoid(),
question: item.question,
answers: allAnswers
};
});
function holdAnswer(id) {
console.log(id);
}
const questionElm = listOfQuestions.map((question, index, i) => {
return (
<section key={index}>
<QuestionSet question={question.question} key={question.id} />
<Answers
answers={question.answers}
isChosen={question.isChosen}
holdAnswer={holdAnswer}
/>
</section>
);
});
return (
<main className="quest-box">
<section className="quest-content">{questionElm}</section>
<button className="answer-btn">Check Answers</button>
{loading && <div>Loading data...</div>}
{error && <div>{`There is a problem fetchning data = ${error}`}</div>}
</main>
);
}
Answers.js
export default function Answers(props) {
console.log(props);
const styles = {
backgroundColor: props.isChosen ? "#D6DBF5" : "transparent"
};
return (
<section className="answer-container">
<div
className="answer-div"
style={styles}
id={props.answers[3].id}
onClick={() => props.holdAnswer(props.answers[3].id)}
>
<p>{props.answers[3].answer}</p>
</div>
<div
className="answer-div"
style={styles}
id={props.answers[1].id}
onClick={() => props.holdAnswer(props.answers[3].id)}
>
<p>{props.answers[1].answer}</p>
</div>
<div
className="answer-div"
style={styles}
id={props.answers[2].id}
onClick={() => props.holdAnswer(props.answers[3].id)}
>
<p>{props.answers[2].answer}</p>
</div>
<div
className="answer-div"
style={styles}
id={props.answers[0].id}
onClick={() => props.holdAnswer(props.answers[3].id)}
>
<p>{props.answers[0].answer}</p>
</div>
</section>
);
}
Here is a working solution
https://codesandbox.io/s/vigilant-silence-tg43w0?file=/src/Answers.js:0-1116
Just to mention, there are a few optimization to be done for the code, but since it doesn't affect the question, I left it out, we can pick that off in the comment section

How to apply styling to a specific item in an array

I'm trying to make a simple todo in react. I want to be able to click in the button next to the todo text and mark it as complete, with a line passing through it, so I guess the point of the button would be to toggle between the two stylings. But I don't know how to apply the styling to that specific todo. Here's my code so far:
import React, { useState } from 'react';
function App() {
const [todos, setTodos] = useState([])
const toggleComplete = (i) => {
setTodos(todos.map((todo, k) => k === i ? {
...todo, complete: !todo.complete
} : todo))
}
const handleSubmit = (event) => {
event.preventDefault()
const todo = event.target[0].value
setTodos((prevTodos) => {
return [...prevTodos, {
userTodo: todo, completed: false, id: Math.random().toString()
}]
})
}
return (
<div>
<form onSubmit={handleSubmit}>
<input placeholder='name'></input>
<button type='submit'>submit</button>
</form>
<ul>
{todos.map((todos) => <li key={todos.id}>
<h4>{
todos.completed ? <s><h4>{todos.userTodo}</h4></s> : <h4>{todos.userTodo}</h4>}
</h4>
<button onClick={toggleComplete}>Mark as complete</button>
</li>)}
</ul>
</div>
);
}
export default App;
You can see that the toggleComplete function takes a parameter i which is the id of the todo, so you should call it like onClick={() => toggleComplete(todos.id)}.
However this still didn't work since you are assigning random numbers as strings as id to the todos then iterating over the array.
As Alex pointed out, there's a bug in your code regarding the completed toggle, so I fixed it and here's a working version of the code you can take a look at and improve:
import React, { useState } from "react";
export default function App() {
const [todos, setTodos] = useState([]);
const toggleComplete = (i) => {
setTodos(
todos.map((todo, k) => {
return k === i
? {
...todo,
completed: !todo.completed
}
: todo;
})
);
};
const handleSubmit = (event) => {
event.preventDefault();
const todo = event.target[0].value;
setTodos((prevTodos) => {
return [
...prevTodos,
{
userTodo: todo,
completed: false,
id: prevTodos.length
}
];
});
};
return (
<div>
<form onSubmit={handleSubmit}>
<input placeholder="name"></input>
<button type="submit">submit</button>
</form>
<ul>
{todos.map((todo) => (
<li key={todo.id}>
{todo.completed ? (
<s>
<p>{todo.userTodo}</p>
</s>
) : (
<p>{todo.userTodo}</p>
)}
<button onClick={() => toggleComplete(todo.id)}>
Mark as complete
</button>
</li>
))}
</ul>
</div>
);
}
There are 2 problems in your code as i see:
typo in the toggleComplete function
Fix: the following code complete: !todo.complete shopuld be completed: !todo.completed as this is the name of the key that you're setting below on handleSubmit.
the toggleComplete function receives as an argument the javascript event object and you are comparing it with the key here:
(todo, k) => k === i
(see more here:
https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event)
Fix: You can modify the lines of code for the todo render as follows:
{todos.map((todo, index) => <li key={todo.id}>
<React.Fragment>{
todo.completed ? <del><h4>{todo.userTodo}</h4></del> : <h4>{todo.userTodo}</h4>}
</React.Fragment>
<button onClick={() => {toggleComplete(index)}}>Mark as complete</button>
</li>)}

How to get answers from multiple components in ReactJS?

I'm working on a survey project, where I'm having a react component 'Questions', a child component 'QuestionOptions' with multiple children 'Radio', 'TextBox', 'Checkbox'.
Some questions in the database have options (multiple choice).
I want to find a way to gather all the answers answered by the user and send them to the database.
This is the Questions component:
const Questions = () => {
const [questions, setQuestions] = useState([])
var game_id = localStorage.getItem('game_id')
useEffect(() => {
axios
.post("http://127.0.0.1:8000/api/v1/questions/get_questions", {
game_id: game_id
})
.then((response) => {
const s = response.data.questions;
setQuestions(s);
});
}, []);
return (
<div>
<ul>
{questions.map((question) => (
<div key={question.id}>
<li key={question.id}>{question.question} ({question.points} points)</li>
<QuestionOptions question_id={question.id} question_type={question.question_type_id}/>
</div>
))}
</ul>
<Button text={"Submit"} id={"submit_btn"}/>
</div>
);
};
This is the QuestionOptions component:
const QuestionOptions = (props) => {
const [options, setOptions] = useState([]);
const question_type = props.question_type;
useEffect(() => {
axios
.post("http://127.0.0.1:8000/api/v1/question_options/get_options", {
question_id: props.question_id,
})
.then((response) => {
setOptions(response.data["options"]);
});
}, [props.question_id]);
if(question_type === 0){
return(
<TextBox />
)
}else if(question_type === 1){
return(
<Radio options={options}/>
)
}else if(question_type === 2){
return(
<Checkbox options={options}/>
)
}
};
The TextBox, Radio and Checkbox components looks as follows:
import React from "react";
const TextBox = () => {
return <input type={"text"} />;
};
export default TextBox;
So I want to get all the answers answered by the user, and disable the submit button if not all questions are answered.
The Questions component looks as follows:
What is your name?
.(input goes here)
What is your favorite color?
. option1
. option2
. option3
What is the best way to make that happen?
Here is example with two types of questions: ones with a save button option, others which update answers directly. Check the output of console.log after you click save button or type answer in the third question.
let questions = [
{ q: 'How old are you?', id: 0 },
{ q: 'How many pets do you have?', id: 1 },
{ q: 'Where were you born?', id: 2, type: 'NoSaveBtn' },
];
let Question = (props) => {
let [value, setValue] = React.useState('');
return (
<div>
<div>{props.q}</div>
<input value={value} onChange={(e) => setValue(e.target.value)}></input>
<button
onClick={() => {
props.onSaveAnswer(value);
}}
>
save answer
</button>
</div>
);
};
let QuestionNoSaveBtn = (props) => {
return (
<div>
<div>{props.q}</div>
<input
value={props.value || ''}
onChange={(e) => props.onSaveAnswer(e.target.value)}
></input>
</div>
);
};
export default function App() {
let [answers, setAnswers] = React.useState({});
console.log(answers);
return (
<div>
{questions.map((x) =>
x.type !== 'NoSaveBtn' ? (
<Question
q={x.q}
key={x.id}
onSaveAnswer={(answer) =>
setAnswers({ ...answers, [x.id]: answer })
}
/>
) : (
<QuestionNoSaveBtn
q={x.q}
key={x.id}
value={answers[x.id]}
onSaveAnswer={(answer) =>
setAnswers({ ...answers, [x.id]: answer })
}
/>
)
)}
</div>
);
}

React memo child component render

I'm having trouble rendering my comment components.
So I have a listComment component and it has 2 child component CommentItem and CommentGroup.
My CommentGroup component is like a dropdown where you can open and close it.
I tried to use React.memo() but it still rendering children thats already rendered
My problem is that every time I add a new comment it renders again the child components that's already rendered. So the comments that's already open the CommentGroup closes. And i use redux for state-management.
PS sorry for the bad english.
Comment Data
[{
body: "comment 1",
comment_counter: 0,
createdAt: "2020-06-14T13:42:38.465Z",
heart_counter: 0,
ownerId: "5edce08cabc7ab1860c7bdf4",
postId: "5ee3770495bfce029842bc68",
_id: "5ee6294eb7295a1c04b62374"
}, {
body: "comment 2",
comment_counter: 0,
createdAt: "2020-06-14T13:42:38.465Z",
heart_counter: 0,
ownerId: "5edce08cabc7ab1860c7bdf4",
postId: "5ee3770495bfce029842bc68",
_id: "5ee6294eb7295a1c04b62374"
}]
ListComments.js
const comments = useSelector(state => state.comment.comments)
return comments.map(comment => {
return (
<div key={comment._id}>
<CommentItem comment={comment} type="post_comment" />
<div className={classes.mLeft}>
<CommentGroup counter={comment.comment_counter} />
</div>
</div >
)
})
CommentGroup.js
const CommentGroup = React.memo((props) => {
const [open, setOpen] = useState(false)
const onOpen = () => {
setOpen(true)
}
const onClose = () => {
setOpen(false)
}
return (
<div>
<Button
size="small"
color="primary"
startIcon={
!open ? <ArrowDropDownOutlinedIcon /> : <ArrowDropUpOutlinedIcon />
}
onClick={
!open ? () => onOpen() : () => onClose()
}
>
{!open ? 'View' : 'Hide'} {1} Replies
</Button>
CommentGroupOpen: {open ? 'true' : 'false'}
</div>
)
}, (prevProps, nextProps) => {
console.log(prevProps) // not getting called
if (prevProps.counter !== nextProps.counter) {
return false
}
return true
})
export default CommentGroup
CommentItem is just a display component
It's likely because that all the comments have the same comment._id which is used as the key. I made a similar example and it worked fine. https://codesandbox.io/s/mutable-framework-stk5g

Categories

Resources