Change React React Child Component在父母的onclick事件中的状态,带有回调和钩子(USESTATE,useFeft)

发布于 2025-01-24 16:21:02 字数 3099 浏览 4 评论 0原文

我的父组件包含一系列类别。该组件呈现一个列表,每个列表项目都有一个复选框,这是子组件。

我将usestate()用于checkedcategory数组,以及子组件复选框的检查/未检查状态。

  • 如果我检查复选框,则将类别添加到列表中。复选框儿童组件的状态(已检查)在子组件(复选框.js)中更新,
  • 如果我取消选中复选框,则该类别将从列表中删除。复选框儿童组件的状态(已检查)在子组件(checkbox.js)中进行了更新。
  • 我有一个“清除所有”按钮,可更新父母的检查效率状态。
  • 每次更新checkedCategory数组时,我都会触发使用使用效果钩的控制台。log,这适用于所有三种情况。

还有一个细节:当单击“清除所有”按钮时,所有复选框都应不选中。因此,我必须以某种方式操纵所有复选框儿童的检查状态。

父元组件:

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;

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.

  • If I check a checkbox, the category is added to the list. The checkbox child component's state (checked) is updated in the child component (Checkbox.js)
  • If I uncheck a checkbox, the category is removed from the list. The checkbox child component's state (checked) is updated in the child component (Checkbox.js).
  • I have a "clear all" button that updates the parent's checkedCategories state.
  • Every time the checkedCategories array is updated, I trigger a console.log with the useEffect hook, and this works for all three cases.

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.

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;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

无人问我粥可暖 2025-01-31 16:21:02

我将完全提高状态到父母,制作复选框组件无状态:

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>
  );
}

从您的父级,您可以将检查属性传递,只需检查该类别是否存在于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/eedit/react-pwxgaq qy? file = src%2fapp.js

I would lift the state completely to the parent making the Checkbox component stateless:

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.

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.

Demo: https://stackblitz.com/edit/react-pwxgaq?file=src%2FApp.js

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文