[英]Change React child component's state from an onClick event in parent, with callbacks and hooks (useState, useEffect)
My parent component contains an array of categories.我的父组件包含一个类别数组。 The component renders a list, and each list item has a checkbox, which is a child component.该组件渲染一个列表,每个列表项都有一个复选框,它是一个子组件。
I use useState() for the checkedCategories array, and for the checked/unchecked state of the the child component Checkbox.我将 useState() 用于 checkedCategories 数组,以及子组件 Checkbox 的选中/未选中 state。
There is one detail left: when the "clear all" button is clicked, all the checkboxes should be unchecked.剩下一个细节:单击“全部清除”按钮时,应取消选中所有复选框。 So I have to manipulate the checked state of all the Checkbox children somehow.所以我必须以某种方式操纵所有 Checkbox 子项的选中 state。
Parent component:父组件:
import {useState, useEffect} from "react";
import Checkbox from "../functions/Checkbox.js";
function CategoryList() {
const categories = ['CategoryA','CategoryB', 'CategoryC']
const [checkedCategories, setCheckedCategories] = useState([]);
const addToCheckedCategories = id => {
const updatedCheckedCategories = [...checkedCategories];
updatedCheckedCategories.push(id);
setCheckedCategories(updatedCheckedCategories);
};
const removeFromCheckedCategories = id => {
const updatedCheckedCategories = checkedCategories.filter(cat => cat !== id);
setCheckedCategories(updatedCheckedCategories);
};
const removeFilters = () => {
//????
}
useEffect(() => {
console.log('checked categories updated');
console.log(checkedCategories);
if (!checkedCategories.length) {
console.log('the array is empty');
//Set all the checkboxes' checked state to "false" somehow...?
}
}, [checkedCategories]);
return(
<div>
<ul>
{categories.map(categories =>
<li key={categories.toLowerCase()}>
<Checkbox id={categories.toLowerCase()}
label={categories}
addToCheckedCategories={addToCheckedCategories}
removeFromCheckedCategories={removeFromCheckedCategories}
/>
</li>
)}
</ul>
<button onClick={removeFilters}>Clear all</button>
</div>
)
}
export default CategoryList;
Child component:子组件:
import { useState } from 'react';
function Checkbox({id, label, addToCheckedCategories, removeFromCheckedCategories}) {
const [checked, setChecked] = useState(false);
const handleChange = id => {
if (checked) {
removeFromCheckedCategories(id);
console.log('removed ' + id);
} else {
addToCheckedCategories(id);
console.log('added ' + id);
}
setChecked(!checked);
console.log('changed value of checkbox');
}
return(
<label htmlFor={id} >
<input type="checkbox"
name="category-input"
id={id}
onChange={handleChange}
/>
{label}
</label>
);
}
export default Checkbox;
I would lift the state completely to the parent making the Checkbox
component stateless:我会将 state 完全提升到父级,使Checkbox
组件无状态:
function Checkbox({
id,
label,
checked,
addToCheckedCategories,
removeFromCheckedCategories,
}) {
const toggle = () => {
if (checked) {
removeFromCheckedCategories(id);
} else {
addToCheckedCategories(id);
}
};
return (
<label htmlFor={id}>
<input
type="checkbox"
name="category-input"
id={id}
onChange={() => toggle()}
checked={checked}
/>
{label}
</label>
);
}
From your parent you can pass down the checked
property simply checking if that category is present in the checkedCategories
array.您可以从您的父母那里传递checked
属性,只需检查该类别是否存在于checkedCategories
数组中。
function CategoryList() {
const categories = ['CategoryA', 'CategoryB', 'CategoryC'];
const [checkedCategories, setCheckedCategories] = useState([]);
const addToCheckedCategories = (id) => {
const updatedCheckedCategories = [...checkedCategories];
updatedCheckedCategories.push(id);
setCheckedCategories(updatedCheckedCategories);
};
const removeFromCheckedCategories = (id) => {
const updatedCheckedCategories = checkedCategories.filter(
(cat) => cat !== id
);
setCheckedCategories(updatedCheckedCategories);
};
// Remove filters is as easy as setting an empty array
const removeFilters = () => {
setCheckedCategories([]);
};
useEffect(() => {
console.log('checked categories updated');
console.log(checkedCategories);
}, [checkedCategories]);
return (
<div>
<ul>
{categories.map((category) => (
<li key={category.toLowerCase()}>
<Checkbox
id={category.toLowerCase()}
label={category}
checked={checkedCategories.includes(category.toLowerCase())}
addToCheckedCategories={addToCheckedCategories}
removeFromCheckedCategories={removeFromCheckedCategories}
/>
</li>
))}
</ul>
<button onClick={removeFilters}>Clear all</button>
</div>
);
}
Using this approach clearing all is very easy, all you have to do is setting the checkedCategories
array to an empty one.使用这种方法清除所有内容非常简单,您所要做的就是将checkedCategories
数组设置为空。
Demo: https://stackblitz.com/edit/react-pwxgaq?file=src%2FApp.js演示: https://stackblitz.com/edit/react-pwxgaq?file=src%2FApp.js
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.