【问题标题】:How to set default state for React toggle custom hook?如何为 React 切换自定义钩子设置默认状态?
【发布时间】:2021-08-25 15:28:16
【问题描述】:

所以场景是,一旦我单击 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 形按钮。

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

提前致谢。

【问题讨论】:

  • 尝试将条件更改为Object.keys(isChevronUp).length &gt; 0 ? !!isChevronUp.containerOne : isChevronUp.defaultObject.keys(isChevronUp).length &gt; 0 ? !!isChevronUp.containerOne : true
  • 只有一个手风琴还是动态的?
  • @Shyam 有多个手风琴必须是动态的
  • @footlessbird 那么手风琴的初始打开状态应该是什么?应该是真的还是假的?
  • @footlessbird 您还可以为 chevrons 钩子添加一个 初始化函数,您将在其中创建一个字段,其键等于 chevron id,默认值等于 true .然后你可以在没有条件的情况下获得人字形值

标签: reactjs typescript lodash


【解决方案1】:

您可以为 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 />
...

【讨论】:

    【解决方案2】:

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

    因此,isChevronUp 应该是您调用的函数,或者您应该使用您的 chevron 的 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')}
    ...
    

    类似的东西

    【讨论】:

    • 好吧,这是默认外观的问题,实际上我对 ChevronButton 和 Accordion 所做的就像 isOpen={!!isChevronUp.containerOne} 一样,没有 useChevron 钩子更改,但如果 chevron 向下并且手风琴是当它刚刚渲染时关闭,这与我想要的完全相反
    猜你喜欢
    • 1970-01-01
    • 2020-05-23
    • 1970-01-01
    • 1970-01-01
    • 2011-08-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-27
    相关资源
    最近更新 更多