通过回调和挂钩(useState、useEffect)从父级的 onClick 事件更改 React 子组件的状态
Change React child component's state from an onClick event in parent, with callbacks and hooks (useState, useEffect)
我的父组件包含一组类别。该组件渲染一个列表,每个列表项都有一个复选框,它是一个子组件。
我对 checkedCategories 数组和子组件 Checkbox 的 checked/unchecked 状态使用 useState()。
- 如果我选中一个复选框,该类别就会添加到列表中。复选框子组件的状态(已选中)在子组件中更新 (Checkbox.js)
- 如果我取消选中某个复选框,该类别将从列表中删除。复选框子组件的状态(已选中)在子组件 (Checkbox.js) 中更新。
- 我有一个“全部清除”按钮,可以更新父级的 checkedCategories 状态。
- 每次更新 checkedCategories 数组时,我都会使用 useEffect 挂钩触发 console.log,这适用于所有三种情况。
还有一个细节:单击“全部清除”按钮时,应取消选中所有复选框。所以我必须以某种方式操纵所有 Checkbox 子项的选中状态。
父组件:
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;
子组件:
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;
我会将状态完全提升到 parent 使 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>
);
}
从您的 parent 您可以传递 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>
);
}
使用这种方法清除所有内容非常简单,您所要做的就是将 checkedCategories
数组设置为空数组。
演示:https://stackblitz.com/edit/react-pwxgaq?file=src%2FApp.js
我的父组件包含一组类别。该组件渲染一个列表,每个列表项都有一个复选框,它是一个子组件。
我对 checkedCategories 数组和子组件 Checkbox 的 checked/unchecked 状态使用 useState()。
- 如果我选中一个复选框,该类别就会添加到列表中。复选框子组件的状态(已选中)在子组件中更新 (Checkbox.js)
- 如果我取消选中某个复选框,该类别将从列表中删除。复选框子组件的状态(已选中)在子组件 (Checkbox.js) 中更新。
- 我有一个“全部清除”按钮,可以更新父级的 checkedCategories 状态。
- 每次更新 checkedCategories 数组时,我都会使用 useEffect 挂钩触发 console.log,这适用于所有三种情况。
还有一个细节:单击“全部清除”按钮时,应取消选中所有复选框。所以我必须以某种方式操纵所有 Checkbox 子项的选中状态。
父组件:
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;
子组件:
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;
我会将状态完全提升到 parent 使 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>
);
}
从您的 parent 您可以传递 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>
);
}
使用这种方法清除所有内容非常简单,您所要做的就是将 checkedCategories
数组设置为空数组。
演示:https://stackblitz.com/edit/react-pwxgaq?file=src%2FApp.js