如何为 React 切换自定义挂钩设置默认状态?

How to set default state for React toggle custom hook?

所以场景是,一旦我单击 V 形按钮,位于 V 形按钮正下方的手风琴组件将打开并显示其子组件。

但是我不希望其他 V 形按钮共享相同的状态,以便只有单击的 V 形按钮和相关的手风琴展开。

默认情况下,一旦模板组件刚刚安装,手风琴就会展开,显示其带有 V 形按钮的子项已启动 ^

代码:

// useChevron hook

import { useState } from 'react';


const useChevron = () => {
  const [isChevronUp, setIsChevronUp] = useState<Partial<any>>({});


  const handleChevron = (id: string) => {
    setIsChevronUp((previousState) => ({
      ...previousState,
      [id]: !previousState[id],
    }));
  };

  return { isChevronUp, setIsChevronUp, handleChevron };
};

export default useChevron;

// template
...
const { handleChevron, isChevronUp } = useChevron();
...

<div id="containerOne">

// when it has just been rendered isChevronUp is empty object so in case set isOpen as true which makes chevron looks like ^ and shows accordion's children
<ChevronButton
            isOpen={_.isEmpty(isChevronUp) ? true : !!isChevronUp.containerOne} 
            id='containerOne'
            onClick={() => handleChevron('containerOne')}
          />
</div>
<Accordion isOpen={_.isEmpty(isChevronUp) ? true : !!isChevronUp.containerOne}>
<ChildrenComponent1 />
<ChildrenComponent2 />
...

除了我必须在第一次点击两次 V 形按钮然后按预期切换正常之外,它似乎可以正常工作。

我在下面试过:

const [isChevronUp, setIsChevronUp] = useState<Partial<SomeType>>({
      'default': true
});
...

<ChevronButton
            isOpen={Object.keys(isChevronUp).length === 1 ? isChevronUp.default : !!isChevronUp.containerOne} 
            id='containerOne'
            onClick={() => handleChevron('containerOne')}
          />
</div>
<Accordion isOpen={Object.keys(isChevronUp).length === 1 ? isChevronUp.default : !!isChevronUp.containerOne}>

但点击 V 形按钮两次也是一样的。

在这种情况下设置默认人字形和展开手风琴并解决两次点击问题的最佳方法是什么?

提前致谢。

您的问题是您的 isChevronUp 状态挂钩值,它不会告诉您是否选择了指定的 V 形,但包含所选 V 形的对象。

因此,isChevronUp 应该是您调用的函数,或者您应该使用 V 形

id 字符串相应地检查状态
// useChevron hook

import { useState } from 'react';


const useChevron = () => {
  const [chevronState, setChevronState] = useState<Partial<any>>({});


  const handleChevron = (id: string) => {
    setChevronState((previousState) => ({
      ...previousState,
      [id]: !previousState[id],
    }));
  };

  const isChevronUp = (id: string) => Boolean(chevronState[id]);

  return { isChevronUp, handleChevron };
};

export default useChevron;

当你检查它是否打开时:

<ChevronButton
  isOpen={isChevronUp('containerOne')}
...

类似的东西

您可以为 chevrons 挂钩添加一个初始化函数,您将在其中创建一个字段,其键等于 chevron id,默认情况下值为 true。然后你可以在没有条件的情况下获得人字形值

// useChevron hook

import { useState } from 'react';

const useChevron = () => {
  const [isChevronUp, setIsChevronUp, initChevron] = useState<Partial<any>>({});

  const init = (id: string) => {
    setIsChevronUp((previousState) => ({
      ...previousState,
      [id]: true,
    }));
  };

  const handleChevron = (id: string) => {
    setIsChevronUp((previousState) => ({
      ...previousState,
      [id]: !previousState[id],
    }));
  };

  return { isChevronUp, setIsChevronUp, handleChevron, init };
};

export default useChevron;

// template
...
const { handleChevron, isChevronUp, init } = useChevron();

useEffect(() => {
  init('containerOne');
}, []);
...

<div id="containerOne">

// when it has just been rendered isChevronUp is empty object so in case set isOpen as true which makes chevron looks like ^ and shows accordion's children
<ChevronButton
            isOpen={isChevronUp.containerOne} 
            id='containerOne'
            onClick={() => handleChevron('containerOne')}
          />
</div>
<Accordion isOpen={isChevronUp.containerOne}>
<ChildrenComponent1 />
<ChildrenComponent2 />
...