简体   繁体   中英

How to use React component's custom hook with “map”

I'm trying to make a Checkbox component.

Here is my Checkbox.tsx .

import React from "react";
import * as S from "./style";

const Checkbox: React.FC<S.ICheckboxProps> = ({ checked, setChecked }) => {
  return <S.StyledCheckbox checked={checked} onClick={setChecked} />;
};

and this is my useCheckbox.tsx ,

import { useState } from "react";

export const useCheckbox = (initialState: boolean) => {
  const [checked, _setChecked] = useState<boolean>(initialState);
  const setCheckedToggle = () => _setChecked((prev) => !prev);
  const setCheckedTrue = () => _setChecked(true);
  const setCheckedFalse = () => _setChecked(false);
  return { checked, setCheckedToggle, setCheckedTrue, setCheckedFalse };
};

export default Checkbox;

It works good. I can use this like

import Layout from "components/Layout";
import { useCheckbox } from "hooks/useCheckbox";
import Checkbox from "components/Checkbox";

const Home = () => {
  const { checked, setCheckedToggle } = useCheckbox(false);
  return (
    <Layout>
      <Checkbox checked={checked} setChecked={setCheckedToggle} />
    </Layout>
  );
};

export default Home;

But I have trouble in the List component.

List has a Checkbox component, and I have to use this List with data .

const Home = ({data}) => {
  return (
    <Layout>
      {data.map((d) => <List />)}
    </Layout>
  );
};

In this case, is there a way to determine if the list is selected?

If the List has useCheckbox , the Home component doesn't know the checked state.

Should I use useCheckbox in the Home component for data.length times? I think this is not good.

Thanks for reading, and Happy new year.

If you want the checkbox state to exist at the level of Home then you'll need state in the Home component that can handle multiple items, either as an array or object.

Then where you map over data you can pass down checked and setChecked as props to List , with all the logic defined in Home using the item index (or preferably an ID if you have one) in relation to your Home state.

Here's an example of a hook you could use in Home

import { useState } from "react";

export const useCheckboxes = () => {
  const [checkedIds, setCheckedIds] = useState([]);

  const addToChecked = (id) => setCheckedIds((prev) => [...prev, id]);

  const removeFromChecked = (id) =>
    setCheckedIds((prev) => prev.filter((existingId) => existingId !== id));

  const isChecked = (id) => !!checkedIds.find(id);

  const toggleChecked = (id) =>
    isChecked(id) ? removeFromChecked(id) : addToChecked(id);

  return { isChecked, toggleChecked };
};

And you would use it like this

const Home = ({ data }) => {
  const { isChecked, toggleChecked } = useCheckboxes();

  return (
    <Layout>
      {data.map((d) => (
        <List
          key={d.id}
          checked={isChecked(d.id)}
          toggleChecked={() => toggleChecked(d.id)}
        />
      ))}
    </Layout>
  );
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM