useState / setData is not updating - javascript

I am trying to figure out a way to do filter by price and name, but somehow the useState won't update. I printed the result out and it worked on both checkboxes. By the way, is it better to use onChange or onClick on checkbox, both look the same to me. I have watched many tutorials and searched for many possible solutions but I still can't solve this problem.
let product = [
{
name: "tesla",
cost: 500,
},
{
name: "benz",
cost: 1000,
},
{
name: "honda",
cost: 200,
},
{
name: "apple",
cost: 400,
},
];
const [data, setData] = useState(product);
const sortbyprice = () => {
const result = product.sort((a, b) => {
return a.cost > b.cost ? 1 : -1;
});
setData(result);
console.log(result);
};
const sortbyname = () => {
const result = product.sort((a, b) => {
return a.name > b.name ? 1 : -1;
});
setData(result);
console.log(data);
};
return (
<div className="App">
<div className="sort price">
<h3>Sort by price</h3>
<input
type="checkbox"
className="searchbar"
onChange={sortbyprice}
></input>
</div>
<div className="sort name">
<h3>Sort by name</h3>
<input
type="checkbox"
className="searchbar"
onChange={sortbyname}
></input>
</div>
<div className="product-container">
{data.map((item, index) => {
return (
<div className="product" key={index}>
<h2>{item.name}</h2>
<p>{item.cost}</p>
</div>
);
})}
</div>
</div>
);
}

I'm updating my answer in order to cover both cases where product is inside the component or outside.
The problem is the array mutation
You can read more here How can you sort an array without mutating the original array?
The correct way is the following and it should work
const sortbyprice = () => {
let dataClone = [...data];
const result = dataClone.sort((a, b) => {
return a.cost > b.cost ? 1 : -1;
});
setData(result);
console.log(result);
};
const sortbyname = () => {
let dataClone = [...data];
const result = dataClone.sort((a, b) => {
return a.name > b.name ? 1 : -1;
});
Check this sandbox

You have to use two different state variables for the this check boxes, and when clicking on one of these you have to update your state accordingly here is CodesandBox.

This all looks good, I run it on codesandbox and it does rerenders. But anyway I would suggest you to move product array out of the component, and just to use it as initial value for useState hook, and on state update use input parameter from setData callback - eg: setData(prev => [...prev.sort(...)]), no need each time to reference initial array since you already used it when calling hook in your component.

Related

What should i do to change select options after changeing previous input without one step gap? react

I have an input with label "Ilosc osob". When I change it, I want to change the Select's options, depends of number in input. It happens, but with one step gap. What should I do?
matchedTables depends on props.tables, and it is filtered array from parent component.
const ReservationForm = (props) => {
const [enteredSize, setEnteredSize] = useState("");
const [enteredTable, setEnteredTable] = useState("");
const [enteredDate, setEnteredDate] = useState("");
const [enteredTime, setEnteredTime] = useState("");
const [sizeMatchedTables, setSizeMatchedTables] = useState([
{ id: 55, table_size: 1, isBusy: false },
{ id: 56, table_size: 2, isBusy: true },
]);
//some code
const matchingSizeTablesHandler = () => {
const newArray = props.tables.filter((tables) => {
if (tables.table_size >= enteredSize) {
return tables;
}
});
setSizeMatchedTables(newArray);
};
const sizeChangeHandler = (event) => {
setEnteredSize(event.target.value);
matchingSizeTablesHandler();
};
//some code
return(
<div>
<div className="new-reservation__control">
<label>Ilość osób</label>
<input
type="number"
min={1}
max={10}
value={enteredSize}
onChange={sizeChangeHandler}
/>
</div>
<select
className="new-reservation__control"
value={enteredTable}
onChange={tableChangeHandler}
>
<TablesInSelect passedOptions={sizeMatchedTables} />
</select>
</div>
)};
const TablesInSelect = (props) => {
return (
<>
{props.passedOptions.map((option, index) => {
return (
<option key={index} value={option.id}>
{option.id}
</option>
);
})}
</>
);
};
I found workaround this problem, but dont think its best way to do this. I changed matchingSizeTableHandler so it work with argument (and also change filter to reduce but it is not the case):
const matchingSizeTablesHandler = (size) => {
const newArray = props.tables.reduce((newTables, tables) => {
if (tables.table_size >= size) {
var newValue = tables;
newTables.push(newValue);
}
if (size === "") newTables = [];
return newTables;
}, []);
setSizeMatchedTables(newArray);
};
and then, in sizeChangeHandler I changed call out matchingSizeTableHandler with event.target.value parameter
const sizeChangeHandler = (event) => {
setEnteredSize(event.target.value);
matchingSizeTablesHandler(event.target.value);
};
. If someone can explain to me the other way to implement this, using the sizeMatchedTable state as a parameter in matchingSizeTablesHandler function, I would be thankful.

How can I re-render an instance of an element generated while mapping an array in react js?

I'm working on this trivia game, fetching the trivia from Trivia Open DB API. The questions are multiple choice, the correct_answer is a key / value pair, while the incorrect_answer is a key with a value of an array with three incorrect answers, therefore I created a new array with the incorrect answer and randomly inserted the correct answer to that array.
I mapped that array to render once instance for each element of the array and I want to only re-render (change the background color) of the clicked answer, but can't figure out how to do this. I console logged my solution to determine if you clicked the correct answer or not, and it works, but can't figure out how to re-render just the instance that was clicked instead of all the jsx elements of the array. Here's my code:
import React, {useState, useEffect} from 'react'
import { nanoid } from 'nanoid'
export default function Question(){
const [questions, setQuestions] = useState("")
useEffect(function() {
fetch(`https://opentdb.com/api.php?amount=10&category=26&type=multiple`)
.then(res => res.json())
.then(data => setQuestions(data.results.map(triviaQuestion =>{
const randomPosition = Math.floor(Math.random()*4)
const questionDisplayed = triviaQuestion.question;
const incorrectAnswersArray = triviaQuestion.incorrect_answers;
incorrectAnswersArray.splice(randomPosition, 0, triviaQuestion.correct_answer)
const possibleAnsewrs = incorrectAnswersArray.map(answer => answer)
function selectAnswer(event){
event.target.id == possibleAnsewrs.indexOf(triviaQuestion.correct_answer) ? console.log("Correct!!") : console.log("Incorrect, the answer is: "+triviaQuestion.correct_answer + " " + possibleAnsewrs.indexOf(triviaQuestion.correct_answer))
}
const allAnswers = incorrectAnswersArray.map(answer =>
<p
id={possibleAnsewrs.indexOf(answer)}
key={nanoid()}
onClick={selectAnswer}
className="question--answers"
>
{answer}
</p>)
return (
<div
key={nanoid()} className='question--container'
>
<h3 key={nanoid()} className="question" >{questionDisplayed}</h3>
<div
key={nanoid()} className='question--answer-container'>
{allAnswers}
</div>
</div>
)
}
)))
},[])
return(
<div>
{questions}
</div>
)
}
You should not store JSX in state, store only the data and render the JSX from state. When an answer is clicked you update the state. When state is updated it will trigger a rerender of your UI. What you update is up to you.
Example:
function Question() {
const [questions, setQuestions] = useState([]);
useEffect(function () {
fetch(`https://opentdb.com/api.php?amount=10&category=26&type=multiple`)
.then((res) => res.json())
.then((data) => {
setQuestions(
data.results.map((question) => ({
id: nanoid(),
...question,
answers: [
...question.incorrect_answers,
question.correct_answer
].sort(() => Math.random() - 0.5)
}))
);
});
}, []);
const selectAnswer = (question) => (event) => {
event.target.id === question.correct_answer
? console.log("Correct!!")
: console.log("Incorrect, the answer is: " + question.correct_answer);
setQuestions((questions) =>
questions.map((el) =>
el.id === question.id
? {
...el,
answered: event.target.id,
isCorrect: event.target.id === question.correct_answer
}
: el
)
);
};
return (
<div>
{questions.map((question) => {
return (
<div key={question.id} className="question--container">
<h3
className="question"
dangerouslySetInnerHTML={{ __html: question.question }}
/>
<div className="question--answer-container">
{question.answers.map((answer) => (
<p
key={answer}
id={answer}
onClick={selectAnswer(question)}
className={[
"question--answers",
question.answered === answer &&
(question.isCorrect ? "correct" : "incorrect")
]
.filter(Boolean)
.join(" ")}
>
{answer}
</p>
))}
</div>
</div>
);
})}
</div>
);
}
CSS
correct {
background-color: lightgreen;
border: 1px solid green;
border-radius: 1rem;
}
.incorrect {
background-color: lightcoral;
border: 1px solid red;
border-radius: 1rem;
}
You are tracking your answers by assigning them an ID, but you're not doing the same for your questions, so we have no way of knowing which question's answer needs to be updated.
You could have two seperate state, one for questions and the other for answers, and for the answers state you could assign an ID that is linked to it's question, but I prefer to simply nest the answers inside the question itself.
Here is my implementation:
import React, { useState, useEffect } from "react";
import { nanoid } from "nanoid";
import "./style.css";
function shuffle(array) {
let currentIndex = array.length,
randomIndex;
// While there remain elements to shuffle...
while (currentIndex != 0) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
// And swap it with the current element.
[array[currentIndex], array[randomIndex]] = [
array[randomIndex],
array[currentIndex],
];
}
return array;
}
function parseClass(answerData) {
if (answerData.clicked) {
if (answerData.correct) {
console.log("Returning correct answer");
return "correct_answer";
} else {
console.log("Returning incorrect answer");
return "incorrect_answer";
}
}
}
export default function Question() {
const [questions, setQuestions] = useState([]);
function handleAnswerClick(questionID, answerID) {
const questionIndex = questions.findIndex(
(question) => question.ID === questionID
);
const answerIndex = questions[questionIndex].answers.findIndex(
(answer) => answer.ID === answerID
);
const newQuestions = [...questions];
// Update the clicked property
newQuestions[questionIndex].answers[answerIndex].clicked = true;
setQuestions(newQuestions);
}
useEffect(function () {
fetch(`https://opentdb.com/api.php?amount=10&category=26&type=multiple`)
.then((res) => res.json())
.then((data) => {
const questionsData = data.results.map(
(questionData, questionIndex) => {
// Map the incorrect answers into an array and give them a property "correct" that is assigned to false, and "clicked" that is assigned to false
let answers = questionData.incorrect_answers.map((answer) => ({
answer,
correct: false,
clicked: false,
}));
// Push the correct answer and give it property "correct" assigned to true, and "clicked" that is assigned to false
answers.push({
answer: questionData.correct_answer,
correct: true,
clicked: false,
});
// Shuffle the answers array using above helper function
answers = shuffle(answers);
answers = answers.map((answer, answerIndex) => ({
// Spread the values of each object in answers array
...answer,
// Add an ID property to each answer
ID: `${questionIndex}-${answerIndex}`,
}));
return {
// Spread the values of each object in data.results array
...questionData,
// Add the answers array we created earlier
answers,
// Add property, call it ID
ID: questionIndex,
};
}
);
setQuestions(questionsData);
});
}, []);
return (
<div>
{questions.length &&
questions.map((questionData) => (
<div key={questionData.ID}>
<p>{questionData.question}</p>
<br />
<ul>
{questionData.answers.map((answerData) => (
<li
key={answerData.ID}
onClick={() =>
handleAnswerClick(questionData.ID, answerData.ID)
}
className={parseClass(answerData)}
>
{answerData.answer}
</li>
))}
</ul>
</div>
))}
</div>
);
}

Map function increment on global react context state

I need some help with incrementing a value through map function while using React's context API. Here is an example to better understand:
Let's say I have items:
const [items, setItems] = useContext(ItemsContext)
These items are JSON objects inside an array.
And then I want to return each item's properties in a list but some of them modified - for example, the item has quantity and I want to increment/decrement it on click. How do I achieve this individually for every item?
I tried making a local state for the quantities:
const [quantity, setQuantity] = useState([])
,so I have all the quantities of all elements but it got me nowhere.
The thing I am trying to accomplish is similar to this:
<div>
<ul>
{
items.map(item => (
<li>
<p>item.name</p>
<p>item.quantity</p>
<button onClick={incQuantity}> </button>
</li>
}
</ul>
</div>
Edit:
const [idCounter, setIdCounter] = useState(0)
I use props. here because this is another component.
const addItem = () => {
if (quantity > 0) {
setIdCounter(idCounter + 1)
setItems(prevItems => [...prevItems, {id: idCounter, name: props.name, price: props.price, quantity: quantity }])
}
}
And I implemented the handler quite the same:
const quantityHandler = (id, diff) => {
setItems(items.map((item) =>
item.id === id ? {...item, quantity: item.quantity + diff} : item
))
}
And here is the list itself:
<div>
<ul>
{
items.map(item => (
<li>
<p>item.name</p>
<p>item.quantity</p>
<button onClick={() => quantityHandler(item.id, 1)}> </button>
<button onClick={() => quantityHandler(item.id, -1)}> </button>
</li>
}
</ul>
</div>
Here is working example and I will explain it a little: in App we make MyContext and state with hook, then we provide state and function to update state to Context provider as value. Then in any place inside Provider we have access to that state and setter. We render items and we can update them using hook setter from Context.
import React, { useState, useContext } from "react";
const MyContext = React.createContext(null);
const initialState = [
{ id: 1, quantity: 1 },
{ id: 2, quantity: 2 },
{ id: 3, quantity: 3 },
{ id: 4, quantity: 4 },
];
const DeepNestedComponent = () => {
const [stateFromContext, setStateFromContext] = useContext(MyContext);
// MyContext should be imported
const buttonHandler = (id, diff) => {
setStateFromContext(
stateFromContext.map((item) =>
item.id === id ? { ...item, quantity: item.quantity + diff } : item
)
);
};
return (
<div>
{stateFromContext.map(({ id, quantity }) => (
<div key={id}>
{quantity}
<button onClick={() => buttonHandler(id, 1)}> + </button>
<button onClick={() => buttonHandler(id, -1)}> - </button>
</div>
))}
</div>
);
};
const App = () => {
const [contextState, setContextState] = useState(initialState);
return (
<MyContext.Provider value={[contextState, setContextState]}>
<DeepNestedComponent />
</MyContext.Provider>
);
};
export default App;
Like it if its is working )

How to prevent a whole list from re-rendering when editing an element on the list?

I created this very simple app to hopefully explain this problem.
I tried using memoization and callback, but I believe it's re-rendering because the playerArr is always changing once I type into the text input.
my actual lists are only 15 elements in size, but the re-render is causing it to become REALLY SLOW when typing into the input.
Any suggestions? I have a deadline and i'm getting stressed out =( will going back to non-hooks help? or implementing redux? not sure the performance factor.
function App() {
const [player1, setPlayer1] = React.useState({
firstName: "First",
lastName: "Last ",
id: uuidv4()
});
const [player2, setPlayer2] = React.useState({
firstName: "First",
lastName: "Last",
id: uuidv4()
});
const [player3, setPlayer3] = React.useState({
firstName: "First",
lastName: "Last",
id: uuidv4()
});
return (
<div>
<State
player1={player1}
player2={player2}
player3={player3}
setPlayer1={setPlayer1}
setPlayer2={setPlayer2}
setPlayer3={setPlayer3}
/>
</div>
);
}
//----------------------------------------------------------
export const State = React.memo(({player1, player2, player3, setPlayer1, setPlayer2, setPlayer3}) => {
const playerArr = [player1, player2, player3];
const setPlayerArr = [setPlayer1, setPlayer2, setPlayer3];
return (
<div>
<Playlist
playerArr={playerArr}
setPlayerArr={setPlayerArr}
/>
</div>
);
});
//----------------------------------------------------------
export const Playlist = React.memo(({playerArr, setPlayerArr}) => {
return (
<div>
{
playerArr.map((player, index) => (
<Player
key={player.id}
player={player}
setPlayer={setPlayerArr[index]}
/>
))
}
</div>
);
});
//----------------------------------------------------------
export const Player = React.memo(({player, setPlayer}) => {
const handleOnChange = React.useCallback((event) => {
const playerCopy = {...player};
playerCopy[event.target.name] = event.target.value;
setPlayer(playerCopy);
}, [player, setPlayer]);
return (
<div>
<input type={"text"} name={"firstName"} value={player.firstName} onChange={handleOnChange}/>
<input type={"text"} name={"lastName"} value={player.lastName} onChange={handleOnChange}/>
</div>
);
});
EDIT: i edited app per discussion. same thing happening
No matter what you do, your <App> and <Playlist> components (even if they are memoized) will HAVE to re-render every time there is a user input because that is where you are storing your state, and is to be expected.
The best you can do is memoize each <Player> component so that when the list re-renders, every individual list item doesn't necessarily re-render itself. To do this you can pass an "areEqual" function as the second argument to React.memo. See the example in the React documentation: https://reactjs.org/docs/react-api.html#reactmemo
In your case, it would probably look something like this:
export const Player = React.memo(({player, setPlayer}) => {
const handleOnChange = React.useCallback((event) => {
const playerCopy = {...player};
playerCopy[event.target.name] = event.target.value;
setPlayer(playerCopy);
}, [player, setPlayer]);
return (
<div>
<input type={"text"} name={"firstName"} value={player.firstName} onChange={handleOnChange}/>
<input type={"text"} name={"lastName"} value={player.lastName} onChange={handleOnChange}/>
</div>
);
}, (prevProps, nextProps) => {
// Check to see if the data is the same
if (prevProps.firstName === nextProps.firstName
&& prevProps.lastName === nextProps.lastName
&& prevProps.id === nextProps.id) {
return true; // Return true if they ARE the same
} else {
return false; // Return false if they are NOT the same
}
});
Sometimes, if the data you are comparing is a simple collection of strings and/or numbers, you can use JSON.stringify as a shorthand way to convert it to a string and compare the strings:
export const Player = React.memo(({player, setPlayer}) => {
const handleOnChange = React.useCallback((event) => {
const playerCopy = {...player};
playerCopy[event.target.name] = event.target.value;
setPlayer(playerCopy);
}, [player, setPlayer]);
return (
<div>
<input type={"text"} name={"firstName"} value={player.firstName} onChange={handleOnChange}/>
<input type={"text"} name={"lastName"} value={player.lastName} onChange={handleOnChange}/>
</div>
);
}, (prevProps, nextProps) => {
// Check to see if the data is the same
if (JSON.stringify(prevProps) === JSON.stringify(nextProps)) {
return true; // Return true if they ARE the same
} else {
return false; // Return false if they are NOT the same
}
});

How to implement multiple checkbox using react hook

I want to implement multiple checkboxes on my HTML page using react-hook.
I tried implementing using this URL: https://medium.com/#Zh0uzi/my-concerns-with-react-hooks-6afda0acc672. In the provided link it is done using class component and working perfectly but whenever I am using React hook setCheckedItems to update checkbox checked status it's not re-rendering the view.
The very first time the view is rendering and console.log() is printing from Checkbox component. After clicking on checkbox function handleChange gets called and checkedItems updates the value but the view is not rendering again (no console.log() printing). And {checkedItems.get("check-box-1")} is also not printing any value.
Below is my sample code.
CheckboxExample :
import React, { useState } from 'react';
import Checkbox from '../helper/Checkbox';
const CheckboxExample = () => {
const [checkedItems, setCheckedItems] = useState(new Map());
const handleChange = (event) => {
setCheckedItems(checkedItems => checkedItems.set(event.target.name, event.target.checked));
console.log("checkedItems: ", checkedItems);
}
const checkboxes = [
{
name: 'check-box-1',
key: 'checkBox1',
label: 'Check Box 1',
},
{
name: 'check-box-2',
key: 'checkBox2',
label: 'Check Box 2',
}
];
return (
<div>
<lable>Checked item name : {checkedItems.get("check-box-1")} </lable> <br/>
{
checkboxes.map(item => (
<label key={item.key}>
{item.name}
<Checkbox name={item.name} checked={checkedItems.get(item.name)} onChange={handleChange} />
</label>
))
}
</div>
);
}
export default Example;
Checkbox:
import React from 'react';
const Checkbox = ({ type = 'checkbox', name, checked = false, onChange }) => {
console.log("Checkbox: ", name, checked);
return (<input type={type} name={name} checked={checked} onChange={onChange} /> )
}
export default Checkbox;
I don't think using a Map to represent the state is the best idea.
I have implemented your example using a plain Object and it works:
https://codesandbox.io/s/react-hooks-usestate-xzvq5
const CheckboxExample = () => {
const [checkedItems, setCheckedItems] = useState({}); //plain object as state
const handleChange = (event) => {
// updating an object instead of a Map
setCheckedItems({...checkedItems, [event.target.name] : event.target.checked });
}
useEffect(() => {
console.log("checkedItems: ", checkedItems);
}, [checkedItems]);
const checkboxes = [
{
name: 'check-box-1',
key: 'checkBox1',
label: 'Check Box 1',
},
{
name: 'check-box-2',
key: 'checkBox2',
label: 'Check Box 2',
}
];
return (
<div>
<lable>Checked item name : {checkedItems["check-box-1"]} </lable> <br/>
{
checkboxes.map(item => (
<label key={item.key}>
{item.name}
<Checkbox name={item.name} checked={checkedItems[item.name]} onChange={handleChange} />
</label>
))
}
</div>
);
}
EDIT:
Turns out a Map can work as the state value, but to trigger a re-render you need to replace the Map with a new one instead of simply mutating it, which is not picked by React, i.e.:
const handleChange = (event) => {
// mutate the current Map
checkedItems.set(event.target.name, event.target.checked)
// update the state by creating a new Map
setCheckedItems(new Map(checkedItems) );
console.log("checkedItems: ", checkedItems);
}
but in this case, I think there is no benefit to using a Map other than maybe cleaner syntax with .get() and .set() instead of x[y].
As an alternative to Map, you might consider using a Set. Then you don't have to worry about initially setting every item to false to mean unchecked. A quick POC:
const [selectedItems, setSelectedItems] = useState(new Set())
function handleCheckboxChange(itemKey: string) {
// first, make a copy of the original set rather than mutating the original
const newSelectedItems = new Set(selectedItems)
if (!newSelectedItems.has(itemKey)) {
newSelectedItems.add(itemKey)
} else {
newSelectedItems.delete(itemKey)
}
setSelectedItems(newSelectedItems)
}
...
<input
type="checkbox"
checked={selectedItems.has(item.key)}
onChange={() => handleCheckboxChange(item.key)}
/>
Seems a bit of a long way round but if you spread the map out and apply it to a new Map your component will re-render. I think using a Object reference instead of a Map would work best here.
const {useState} = React
const Mapper = () => {
const [map, setMap] = useState(new Map());
const addToMap = () => {
const RNDM = Math.random().toFixed(5)
map.set(`foo${RNDM}`, `bar${RNDM}`);
setMap(new Map([...map]));
}
return (
<div>
<ul>
{[...map].map(([v, k]) => (
<li key={k}>
{k} : {v}
</li>
))}
</ul>
<button onClick={addToMap}>add to map</button>
</div>
);
};
const rootElement = document.getElementById("react");
ReactDOM.render(<Mapper />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>
As a supplement to using a single object to hold the state of numerous items, the updates will not occur as expected if updating multiple items within a single render. Newer commits within the render cycle will simply overwrite previous commits.
The solution to this is to batch up all the changes in a single object and commit them all at once, like so:
// An object that will hold multiple states
const [myStates, setMyStates] = useState({});
// An object that will batch all the desired updates
const statesUpdates = {};
// Set all the updates...
statesUpdates[state1] = true;
statesUpdates[state2] = false;
// etc...
// Create a new state object and commit it
setMyStates(Object.assign({}, myStates, statesUpdates));
export default function Input(props) {
const {
name,
isChecked,
onChange,
index,
} = props;
return (
<>
<input
className="popup-cookie__input"
id={name}
type="checkbox"
name={name}
checked={isChecked}
onChange={onChange}
data-action={index}
/>
<label htmlFor={name} className="popup-cookie__label">{name}</label>
</>
);
}
const checkboxesList = [
{name: 'essential', isChecked: true},
{name: 'statistics', isChecked: false},
{name: 'advertising', isChecked: false},
];
export default function CheckboxesList() {
const [checkedItems, setCheckedItems] = useState(checkboxesList);
const handleChange = (event) => {
const newCheckboxes = [...checkedItems];
newCheckboxes[event.target.dataset.action].isChecked = event.target.checked;
setCheckedItems(newCheckboxes);
console.log('checkedItems: ', checkedItems);
};
return (
<ul className="popup-cookie-checkbox-list">
{checkboxesList.map((checkbox, index) => (
<li className="popup-cookie-checkbox-list__item" key={checkbox.name}>
<Input
id={checkbox.name}
name={checkbox.name}
isChecked={checkbox.isChecked}
onChange={handleChange}
index={index}
/>
</li>
))}
</ul>
);
}```

Categories

Resources