React Function Components - following parent component state - reactjs

I'm new to react and I'm trying component functional style.
I have simple todo list. I would like to strike out todo item from list using style property. From Chrome debug mode I do not see immediate reaction on checkbox changes, also Item is not striked out... It seams to me, that it is problem with how I manage state of components. I would appreciate some guidance.
App.js
import React, {useState} from 'react';
import Todos from "./components/Todos";
import './App.css'
const App = () => {
const [todos, setTodos] = useState(
[
{id: 1, title: 'Take out the trash', completed: false},
{id: 2, title: 'Dinner with wife', completed: false},
{id: 3, title: 'Meeting boss', completed: false}
]
);
const markComplete = id => {
console.log((new Date()).toString());
todos.map(todo => {
if (todo.id === id) {
todo.completed = ! todo.completed;
}
return todo;
});
setTodos(todos);
};
return (
<div className="App">
<Todos todos={todos} markComplete={markComplete}/>
</div>
);
};
export default App;
Todos.js
import React from "react";
import TodoItem from "./TodoItem";
const Todos = ({todos, markComplete}) => {
return (
todos.map(todo => (
<TodoItem key={todo.id} todoItem={todo} markComplete={markComplete} />
))
);
};
export default Todos;
TodoItem.js
import React from "react";
const TodoItem = ({todoItem, markComplete}) => {
const getStyle = () => {
console.log("style: " + todoItem.completed);
return {
background: '#f4f4f4',
padding: '10px',
borderBottom: '1px #ccc dotted',
textDecoration: todoItem.completed ? 'line-through' : 'none'
}
};
return (
<div style={getStyle()}>
<p>
<input type="checkbox" onChange={markComplete.bind(this, todoItem.id)}/>{' '}
{todoItem.title}
</p>
</div>
);
};
export default TodoItem;
I expect that this getStyle() will follow state... somehow...

Don't mutate state. In markComplete function, you are mutating the todos array directly. Change your function like this to avoid mutation
const markComplete = id => {
console.log((new Date()).toString());
let newTodos = todos.map(todo => {
let newTodo = { ...todo };
if (newTodo.id === id) {
newTodo.completed = !newTodo.completed;
}
return newTodo;
});
setTodos(newTodos);
};

Array.prototype.map() returns a new Array, which you are throwing away. You need to use the new array, e.g.:
const markComplete = id => {
...
setTodos(totos.map(...))

Related

Dropdown menu to switch languages in React?

i've been trying to make a dropdown menu component on react to use on my portfolio's landing page. I need the menu to change the text on the website from english to my native language and viceversa so it should contain the options "EN" and "IT" and an image of the two flags, like in the picture i attached.
here's how it looks currently and it works too but i can't/don't know how to add the flags with the < select > element.
import React, { useContext } from "react";
import { languageOptions } from "../languages";
import { LanguageContext } from "../container/Language";
export default function LanguageSelector() {
const { userLanguage, userLanguageChange } = useContext(LanguageContext);
const handleLanguageChange = (e) => userLanguageChange(e.target.value);
return (
<select
onChange={handleLanguageChange}
value={userLanguage}
>
{Object.entries(languageOptions).map(([id, name]) => (
<option key={id} value={id}>
{name}
</option>
))}
</select>
);
}
now:
vs how i want it to look like: (https://i.stack.imgur.com/QDugw.png)
here's what's inside languageContext :
import React, { useState, createContext, useContext } from "react";
import { languageOptions, dictionaryList } from "../languages";
export const LanguageContext = createContext({
userLanguage: "en",
dictionary: dictionaryList.en,
});
export function LanguageProvider({ children }) {
const defaultLanguage = window.localStorage.getItem("rcml-lang");
const [userLanguage, setUserLanguage] = useState(defaultLanguage || "en");
const provider = {
userLanguage,
dictionary: dictionaryList[userLanguage],
userLanguageChange: (selected) => {
const newLanguage = languageOptions[selected] ? selected : "en";
setUserLanguage(newLanguage);
window.localStorage.setItem("rcml-lang", newLanguage);
},
};
return (
<LanguageContext.Provider value={provider}>
{children}
</LanguageContext.Provider>
);
}
export function Text({ tid }) {
const languageContext = useContext(LanguageContext);
return languageContext.dictionary[tid] || tid;
}
and in languageOptions :
import en from "./en.json";
import it from "./it.json";
export const dictionaryList = { en, it };
export const languageOptions = {
en: "EN",
it: "IT",
};
In React I don't think the option element will take an img as a child element (nor will the select element). You could use an unordered list. Crude example below.
const {useState} = React;
const languageOptions = [
{
id: "en",
name: "English",
flagimg:
"https://upload.wikimedia.org/wikipedia/commons/8/83/Flag_of_the_United_Kingdom_%283-5%29.svg",
},
{
id: "it",
name: "Italian",
flagimg: "https://upload.wikimedia.org/wikipedia/en/0/03/Flag_of_Italy.svg",
},
];
const defaultLangFlag = <img src={languageOptions[0].flagimg} height="30" width="30" alt="nope" />;
const Example = () => {
const [cssDisplay, setCssDisplay] = useState('none');
const [langFlag, setLangFlag] = useState(defaultLangFlag)
const showDropdown = () => {
if (cssDisplay === 'none'){
setCssDisplay('block');
} else {
setCssDisplay('none');
}
};
const selectListItem = (event) => {
handleLanguageChange(event);
setCssDisplay('none');
setLangFlag(<img src={event.target.src} height="30" width="30" alt="nope" />)
};
const handleLanguageChange = (event) => userLanguageChange(event);
const userLanguageChange = (event) => {
console.log("Here grab event.target.id and propagate lang change to app");
}
return (
<div>
<button onClick={showDropdown} >{langFlag}</button>
<ul style={{ display: cssDisplay }}>
{languageOptions.map((lang) => (
<li id={lang.id} key={lang.id} disabled>
<img onClick={selectListItem} src={lang.flagimg} height="30" width="30" alt="flagpic" id={lang.id} />
{lang.name}
</li>
))}
</ul>
</div>
);
};
ReactDOM.createRoot(
document.getElementById("root")
).render(
<Example />
);
li {list-style: none;)
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>

React: Overwrite an array with another array. Error: Uncaught TypeError: ...is not a function

I am currently working on a todo app in React. In the function handleClearTodos I would like to delete all todos with the status: Done. To do this, I run through the array todos in this function and write all todos with the status: Open into a new array with the name cleanedTodos. At the end, when I want to overwrite the content of todos with the content of cleanedTodos, I get the following error message:
Uncaught TypeError: currentTodos.forEach is not a function
This is a function in the Todo component which separates the todos with the status: Open from those with the status: Done, stores them in two different arrays and renders them separately in the render function.
TodoTable.js (Parent Component)
import React, {useState} from "react";
import { InputBar } from "./InputBar";
import { Todo } from "./Todo";
let currentTodos = [];
export const TodoTable = ({ mockTodos }) => {
//Konstruktor
if(mockTodos){
currentTodos = mockTodos;
}
const [todos, setTodos] = useState(currentTodos);
const [enterTodo, setEnterTodo] = useState('');
//Enter Todo handler
const handleEnterTodo = (event) => {
setEnterTodo(event.target.value);
};
//Clear Todo handler
const handleClearTodos = (event) => {
let cleanedTodos = []
todos.forEach((element, index) => {
if(todos[index].status != 'open'){
//console.log(todos[index])
cleanedTodos.push(todos[index]);
}
});
setTodos({ todos: cleanedTodos });
console.log(typeof cleanedTodos);
console.log(todos);
}
//Create Todo handler
const handleCreateTodo = (event) => {
//create new Todo
const newTodo = {
id: todos.length,
describtion: enterTodo,
status: 'open'
};
setTodos(todos =>
[
newTodo,
...todos
]
);
};
return(
<>
<InputBar
enterTodo={ enterTodo }
handleEnterTodo={ handleEnterTodo }
handleCreateTodo={ handleCreateTodo }
handleClearTodos= { handleClearTodos }
/>
<Todo currentTodos={ todos } />
</>
);
}
Todo.js (Child Component)
import React from "react";
export const Todo = ({ currentTodos }) => {
let openTodo = [];
let doneTodo = [];
// just for develope
const lineBreak = <hr></hr>
currentTodos.forEach((element, index) => {
if(currentTodos[index].status == 'open'){
let todoOpen = (
<div className="openTodos" key={ currentTodos[index].id.toString() }>
{currentTodos[index].describtion}
{/*Buttons*/}
{/*Buttons*/}
</div>
);
openTodo =
[
...openTodo,
todoOpen
]
}
else{
let todoDone = (
<div className="doneTodos" key={ currentTodos[index].id.toString() }>
{currentTodos[index].describtion}
{/*Buttons*/}
{/*Buttons*/}
</div>
);
doneTodo =
[
...doneTodo,
todoDone
]
}
})
return(
<>
{openTodo}
{lineBreak}
{doneTodo}
</>
);
}
InputBar (Child Component)
import React from "react";
import { Button } from "./components/Button";
export const InputBar = ({ enterTodo, handleEnterTodo, handleCreateTodo, handleClearTodos}) => {
console.log(enterTodo);
return(
<>
<form>
<input
type='text'
value={enterTodo}
onChange={handleEnterTodo}
/>
<Button lable= 'ADD' disabled= { enterTodo == '' } onClick= { handleCreateTodo } />
<Button lable= 'CLEAR' onClick= { handleClearTodos } />
</form>
</>
);
}
Function forEach can be used for variables which are type Array. Your prop currentTodos is not an array, you set this to object:
setTodos({ todos: cleanedTodos });
This code return your todos:
console.log(todos.todos) // returning your cleanedTodos array
But in your parent component you init state as array, so it always should be array

react memoize using React.memo

I Try not to Rerender Persons Component When ShowCockpit State Changes In MainAssignment Component. Like when i do in Cockpit Component, it doesn't rerender When Persons state change.
In This Case We Have 3 Components MainAssignment Component [parnt] , Cockpit Component [child] , Persons Component [child].
/********************************************************/
/*** MainAssignment Component ***/
import React, { useCallback, useState } from 'react';
import Persons from './persons';
import Coockpit from './cockpit';
const MainAssignment = () => {
// All State
const [persons, setPersons] = useState([
{ id: '1', name: 'mustafa', age: 24 },
{ id: '2', name: 'ahmed', age: 25 },
{ id: '3', name: 'saad', age: 26 },
]);
const [showPersons, setShowPersons] = useState(true);
const [showCoockpit, setShowCoockpit] = useState(true);
const togglePersonHandler = useCallback(() => {
setShowPersons(!showPersons);
}, [showPersons]);
// change name in specific object in persons state
const nameChangeHandler = (e, id, personIndex) => {
let newPersons = [...persons];
let person = { ...newPersons[personIndex] };
person.name = e.target.value;
newPersons[personIndex] = person;
setPersons(newPersons);
};
// delete object from persons state
const deletePersonHandler = (personIndex) => {
let newPersons = [...persons];
newPersons.splice(personIndex, 1);
setPersons(newPersons);
};
// Main Render
return (
<>
<button
onClick={() => {
setShowCoockpit((prev) => !prev);
}}
>
remove Coockpit
</button>
{showCoockpit ? (
<div style={{ border: '1px solid' }}>
<Coockpit clicked={togglePersonHandler} personsLength={persons.length} showPersons={showPersons} />
</div>
) : null}
{showPersons ? <Persons persons={persons} clicked={deletePersonHandler} changed={nameChangeHandler} /> : null}
</>
);
};
export default MainAssignment;
/********************************************************/
/*** Cockpit Component ***/
/********************************************************/
/*** Cockpit Component ***/
import React, { useRef } from 'react';
const Cockpit = ({ clicked }) => {
let toggleBtnRef = useRef(null);
console.log('render => Cockpit');
return (
<div>
<h1>hi i'm a main assin from cockpit</h1>
<button className="toggle-persons" onClick={clicked} ref={toggleBtnRef}>
toggle persons
</button>
</div>
);
};
// in Cockpit i use React.memo and it work
export default React.memo(Cockpit);
/********************************************************/
/*** Persons Component ***/
import React, { useEffect, useRef } from 'react';
import Person from './person';
const Persons = ({ persons, clicked, changed }) => {
console.log('render => personssss');
const mainRef = {
allInputPersonRef: useRef([]),
};
return (
<>
{persons?.map((person, idx) => (
<Person
key={idx}
name={person.name}
age={person.age}
position={idx}
index={idx}
ref={mainRef}
click={() => {
clicked(idx);
}}
changed={(e) => {
changed(e, person.id, idx);
}}
/>
))}
</>
);
};
// in Persons i use React.memo and it doesn't work
export default React.memo(Persons);
/********************************************************/
/*** Person Component ***/
import React from 'react';
const Person = React.forwardRef((props, ref) => {
const { allInputPersonRef } = ref;
// value of props
const { name, age, click, changed, children, index } = props;
return (
<div>
<p onClick={click}>
i'm {name} and i'm {age} years old
</p>
<p> i'am props children: {children}</p>
<input type="text" onChange={changed} value={name} ref={(el) => (allInputPersonRef.current[index] = el)} />
<button onClick={click}>delete this person</button>
</div>
);
});
export default Person;
React.memo can prevent children from rerendering when the parent component rerenders.
It compares (by reference) each previous and next prop. When one of them is different React will rerender the child normally.
In your case you are always passing new function to changed prop
const nameChangeHandler = (e, personIndex) => {
let newPersons = [...persons];
let person = { ...newPersons[personIndex] };
person.name = e.target.value;
newPersons[personIndex] = person;
setPersons(newPersons);
};
How to avoid this?
Make sure that nameChangeHandler is the same function each time you need to rerender and you don't want to rerender the Person component. https://reactjs.org/docs/hooks-reference.html#usecallback
const nameChangeHandler = useCallback((e, personIndex) => {
setPersons((persons) => {
let newPersons = [...persons];
let person = { ...newPersons[personIndex] };
person.name = e.target.value;
newPersons[personIndex] = person;
return newPersons
});
}, []);
Similarly you should memorize deletePersonHandler function
const deletePersonHandler = useCallback((personIndex) => {
setPersons((persons)=>{
let newPersons = [...persons];
newPersons.splice(personIndex, 1);
return newPersons
});
}, []);
using useCallback with togglePersonHandler and deletePersonHandler
const nameChangeHandler = useCallback((e, id, personIndex) => {
let newPersons = [...persons];
let person = { ...newPersons[personIndex] };
person.name = e.target.value;
newPersons[personIndex] = person;
setPersons(newPersons);
}, []);
const deletePersonHandler = useCallback((personIndex) => {
let newPersons = [...persons];
newPersons.splice(personIndex, 1);
setPersons(newPersons);
}, []);

Could'nt return maped item inside jsx component

Hey Guys I am trying to display a list of items according to categories,
this is my json structure. I want to display objects according to itemCategory. for e.g if there are two or more pizza they should come under one category heading.
{
"itemid": 3,
"itemName": "Veg OverLoaded",
"itemPrice": 300.0,
"itemDescription": "chessy, tasty, covered with fresh veggies",
"itemCategory": "pizza"
},
for this i created a map of objects and passed the data according to category as key.
import React, { forwardRef,useState } from 'react';
import MenuItem from './MenuItem';
import './styles.css';
import Category from '../../Home/Category'
const NewMap = new Map()
const Menu = forwardRef(({ list }, ref) => (
<>
<main ref={ref} >
{Object.values(list).map((k) => {
if (NewMap.has(k.itemCategory)){
const itemList = NewMap.get(k.itemCategory);
const newItemList = [...itemList, k];
NewMap.set(k.itemCategory, newItemList);
}else{
NewMap.set(k.itemCategory , [k]);
}
})}
<MenuItem itemMap = {NewMap}/>
</main>
</>
));
i am passing the map to MenuItem as props and trying to display objects here
import React, { useState, useEffect } from 'react';
import { connect } from 'react-redux';
import { createStructuredSelector } from 'reselect';
import {
cartAddItem,
cartRemoveItem,
} from '../../../../redux/cart/cart.action';
import {
selectCartItems,
selectCartItemsCount,
} from '../../../../redux/cart/cart.selector';
import ButtonAddRemoveItem from '../../ButtonAddRemoveItem';
import './styles.css';
import Accordion from 'react-bootstrap/Accordion'
import useFetchData from './newData'
const MenuItem = ({
itemMap,
cartCount,
cartList,
cartAddItem,
cartRemoveItem,
}) => {
const {
data,
loading,
} = useFetchData();
const handleQuantity = () => {
let quantity = 0;
if (cartCount !== 0) {
const foundItemInCart = cartList.find((item) => item.itemid === 1);
if (foundItemInCart) {
quantity = foundItemInCart.quantity;
}
}
return quantity;
};
return (
<>
{itemMap.forEach((key, value) => {
{console.log(value)}
<div className='container-menu' >
{console.log(value)}
<ul>
{Object.values(key).map((blah) => {
<li>
<h1>{blah.itemName}</h1>
<div className='item-contents'>
{blah.itemName}
<p className='item-contents' style={{ float: "right", fontSize: "12" }}> ₹ {blah.itemPrice}</p>
<div>
<p className='description'>{blah.itemDescription}</p>
<ButtonAddRemoveItem
quantity={handleQuantity()}
handleRemoveItem={() => cartRemoveItem(blah)}
handleAddItem={() => cartAddItem(blah)}
/>
</div>
</div>
</li>
})}
</ul>
</div>
})}
</>
);
};
const mapStateToProps = createStructuredSelector({
cartCount: selectCartItemsCount,
cartList: selectCartItems,
});
const mapDispatchToProps = (dispatch) => ({
cartAddItem: (item) => dispatch(cartAddItem(item)),
cartRemoveItem: (item) => dispatch(cartRemoveItem(item)),
});
export default connect(mapStateToProps, mapDispatchToProps)(MenuItem);
export default Menu;
i am able to console.log itemName but i am unable to display it inside jsx component. Any reason why
? what am i missing here
The foreach loop should return JSX. In your case there is no return. I suggest removing the curly brackets.
WRONG:
itemMap.forEach((key, value) => {
<>
</>
})
CORRECT:
itemMap.forEach((key, value) => (
<>
</>
))
That's valid for all the loops inside your JSX.
To return an array of elements, you should use map instead of forEach like below code, because forEach loop returns undefined, while map always returns an array.
{itemMap.map((key, value) => {
return (<div className='container-menu'>
...
</div>)
}
}
or
{itemMap.map((key, value) => (<div className='container-menu'>
...
</div>)
}

Having React Context in Separate File, Can't Get Component to Not re-render

I've got a simple example of React Context that uses useMemo to memoize a function and all child components re-render when any are clicked. I've tried several alternatives (commented out) and none work. Please see code at stackblitz and below.
https://stackblitz.com/edit/react-yo4eth
Index.js
import React from "react";
import { render } from "react-dom";
import Hello from "./Hello";
import { GlobalProvider } from "./GlobalState";
function App() {
return (
<GlobalProvider>
<Hello />
</GlobalProvider>
);
}
render(<App />, document.getElementById("root"));
GlobalState.js
import React, {
createContext,useState,useCallback,useMemo
} from "react";
export const GlobalContext = createContext({});
export const GlobalProvider = ({ children }) => {
const [speakerList, setSpeakerList] = useState([
{ name: "Crockford", id: 101, favorite: true },
{ name: "Gupta", id: 102, favorite: false },
{ name: "Ailes", id: 103, favorite: true },
]);
const clickFunction = useCallback((speakerIdClicked) => {
setSpeakerList((currentState) => {
return currentState.map((rec) => {
if (rec.id === speakerIdClicked) {
return { ...rec, favorite: !rec.favorite };
}
return rec;
});
});
},[]);
// const provider = useMemo(() => {
// return { clickFunction: clickFunction, speakerList: speakerList };
// }, []);
//const provider = { clickFunction: clickFunction, speakerList: speakerList };
const provider = {
clickFunction: useMemo(() => clickFunction,[]),
speakerList: speakerList,
};
return (
<GlobalContext.Provider value={provider}>{children}</GlobalContext.Provider>
);
};
Hello.js
import React, {useContext} from "react";
import Speaker from "./Speaker";
import { GlobalContext } from './GlobalState';
export default () => {
const { speakerList } = useContext(GlobalContext);
return (
<div>
{speakerList.map((rec) => {
return <Speaker speaker={rec} key={rec.id}></Speaker>;
})}
</div>
);
};
Speaker.js
import React, { useContext } from "react";
import { GlobalContext } from "./GlobalState";
export default React.memo(({ speaker }) => {
console.log(`speaker ${speaker.id} ${speaker.name} ${speaker.favorite}`);
const { clickFunction } = useContext(GlobalContext);
return (
<>
<button
onClick={() => {
clickFunction(speaker.id);
}}
>
{speaker.name} {speaker.id}{" "}
{speaker.favorite === true ? "true" : "false"}
</button>
</>
);
});
Couple of problems in your code:
You already have memoized the clickFunction with useCallback, no need to use useMemo hook.
You are consuming the Context in Speaker component. That is what's causing the re-render of all the instances of Speaker component.
Solution:
Since you don't want to pass clickFunction as a prop from Hello component to Speaker component and want to access clickFunction directly in Speaker component, you can create a separate Context for clickFunction.
This will work because extracting clickFunction in a separate Context will allow Speaker component to not consume GlobalContext. When any button is clicked, GlobalContext will be updated, leading to the re-render of all the components consuming the GlobalContext. Since, Speaker component is consuming a separate context that is not updated, it will prevent all instances of Speaker component from re-rendering when any button is clicked.
Demo
const GlobalContext = React.createContext({});
const GlobalProvider = ({ children }) => {
const [speakerList, setSpeakerList] = React.useState([
{ name: "Crockford", id: 101, favorite: true },
{ name: "Gupta", id: 102, favorite: false },
{ name: "Ailes", id: 103, favorite: true }
]);
return (
<GlobalContext.Provider value={{ speakerList, setSpeakerList }}>
{children}
</GlobalContext.Provider>
);
};
const ClickFuncContext = React.createContext();
const ClickFuncProvider = ({ children }) => {
const { speakerList, setSpeakerList } = React.useContext(GlobalContext);
const clickFunction = React.useCallback(speakerIdClicked => {
setSpeakerList(currentState => {
return currentState.map(rec => {
if (rec.id === speakerIdClicked) {
return { ...rec, favorite: !rec.favorite };
}
return rec;
});
});
}, []);
return (
<ClickFuncContext.Provider value={clickFunction}>
{children}
</ClickFuncContext.Provider>
);
};
const Speaker = React.memo(({ speaker }) => {
console.log(`speaker ${speaker.id} ${speaker.name} ${speaker.favorite}`);
const clickFunction = React.useContext(ClickFuncContext)
return (
<div>
<button
onClick={() => {
clickFunction(speaker.id);
}}
>
{speaker.name} {speaker.id}{" "}
{speaker.favorite === true ? "true" : "false"}
</button>
</div>
);
});
function SpeakerList() {
const { speakerList } = React.useContext(GlobalContext);
return (
<div>
{speakerList.map(rec => {
return (
<Speaker speaker={rec} key={rec.id} />
);
})}
</div>
);
};
function App() {
return (
<GlobalProvider>
<ClickFuncProvider>
<SpeakerList />
</ClickFuncProvider>
</GlobalProvider>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>
You can also see this demo on StackBlitz
this will not work if you access clickFuntion in children from provider because every time you updating state, provider Object will be recreated and if you wrap this object in useMemolike this:
const provider = useMemo(()=>({
clickFunction,
speakerList,
}),[speakerList])
it will be recreated each time clickFunction is fired.
instead you need to pass it as prop to the children like this:
import React, {useContext} from "react";
import Speaker from "./Speaker";
import { GlobalContext } from './GlobalState';
export default () => {
const { speakerList,clickFunction } = useContext(GlobalContext);
return (
<div>
{speakerList.map((rec) => {
return <Speaker speaker={rec} key={rec.id} clickFunction={clickFunction }></Speaker>;
})}
</div>
);
};
and for provider object no need to add useMemo to the function clickFunction it's already wrapped in useCallback equivalent to useMemo(()=>fn,[]):
const provider = {
clickFunction,
speakerList,
}
and for speaker component you don't need global context :
import React from "react";
export default React.memo(({ speaker,clickFunction }) => {
console.log("render")
return (
<>
<button
onClick={() => {
clickFunction(speaker.id);
}}
>
{speaker.name} {speaker.id}{" "}
{speaker.favorite === true ? "true" : "false"}
</button>
</>
);
});

Resources