I'm learning React and have come to the problem that I do not know how I can get "access" to the "setPeople" from the List.js class.
The GUI looks as followed. GUI
I know how to handle this if I would just do all of it in one class (App.js for example). But by doing it the "clean" way, I can't get the desired solution.
I guess I have to declare the "const [people, setPeople] = useState(data) somewhere else, right?
List.js:
const List = ({ people }) => {
const deletePerson = (id) => {
let newPeople = people.filter((person) => person.id !== id);
console.log(newPeople);
// setPeople(newPeople); // ***how can I access this setPeople method in order to update the list?***
};
return (
<>
{people.map((person) => {
const { id, name, age, image } = person;
return (
<article key={id} className="person">
<img src={image} alt={name} />
<div>
<h4>{name}</h4>
<p>{age}</p>
<button
className="btn"
onClick={() => {
deletePerson({ id });
}}
>
Delete me (HERE)
</button>
</div>
</article>
);
})}
</>
);
};
App.js:
function App() {
const [people, setPeople] = useState(data); //data is just an array of objects
return (
<main>
<section className="container">
<h3>{people.length} birthdays today</h3>
<List people={people}></List>
<button onClick={() => setPeople([])}>Clear all</button>
</section>
</main>
);
}
CodePudding user response:
You could define a callback onDeletePerson
prop on your List
component:
const List = ({ people, onDeletePerson }) => {
const deletePerson = (id) => {
let newPeople = people.filter((person) => person.id !== id);
console.log(newPeople);
onDeletePerson(newPeople);
};
...
};
and then, in your App
component, you retrieve the callback value
function App() {
const [people, setPeople] = useState(data); //data is just an array of objects
const handleOnDeletePerson = (value) => {
setPeople(value);
};
return (
<main>
<section className="container">
<h3>{people.length} birthdays today</h3>
<List people={people} onDeletePerson={handleOnDeletePerson}></List>
<button onClick={() => setPeople([])}>Clear all</button>
</section>
</main>
);
}
Another way would be to use a state management library such as Redux.
CodePudding user response:
You can give the List
component an onDelete
event handler props, it will be triggered when the user clicks the delete button.
Controls the people
state in the App
component, and List
is more like a pure UI component, does not include business logic.
App.js
:
import "./styles.css";
import { useState } from "react";
import List from "./List";
export default function App() {
const [people, setPeople] = useState([
{ id: 1, name: "a", age: 20, image: "" },
{ id: 2, name: "b", age: 20, image: "" },
{ id: 3, name: "c", age: 20, image: "" }
]);
return (
<main>
<section className="container">
<h3>{people.length} birthdays today</h3>
<List
people={people}
onDelete={({ id }) => {
setPeople((pre) => pre.filter((person) => person.id !== id));
}}
></List>
<button onClick={() => setPeople([])}>Clear all</button>
</section>
</main>
);
}
List.js
:
import React from "react";
const List = ({ people, onDelete }) => {
return (
<>
{people.map((person) => {
const { id, name, age, image } = person;
return (
<article key={id} className="person">
<img src={image} alt={name} />
<div>
<h4>{name}</h4>
<p>{age}</p>
<button
className="btn"
onClick={() => {
onDelete({ id });
}}
>
Delete me (HERE)
</button>
</div>
</article>
);
})}
</>
);
};
export default List;
CodePudding user response:
Multiple options to achieve that
- Pass
setPeople
in props toList
- Use React.Context and have
setPeople
in the context, useReact.useContext
hook to access to the context inList
- Use global state (with Redux for example) and you can connect to the shared store in components you need, and dispatch
setPeople
from anywhere