当前位置: 首页 > 知识库问答 >
问题:

在自定义React钩子中返回函数有困难

慕宏儒
2023-03-14

我目前正在尝试创建一个useRadioList()钩子,跟踪给定组件中所有子组件上的isExpanded道具(当一个子组件切换isExpanded时,其他子组件取消切换)

我这样做的方式是:

  1. 通过创建与子节点长度相同的假值列表来设置初始状态
  2. 将此状态映射到每个子的isExpandedprop
  3. 声明并返回操作初始列表状态的切换函数
// useRadioList.jsx
import React, { Children, isValidElement, cloneElement, useState, useEffect } from "react"

export default (children, allowMultiple = true) => {


// 1) Setup initial list 

  const [radioList, setRadioList] = useState(Array(children.length).fill(false))

// 2) Map radioList values to component children on initial render, and do so again if radioList changes

  useEffect(() => {

    Children.map(children, (child, idx) => {
      if (!isValidElement(child)) {return}

      return cloneElement(child, {isExpanded: radioList[idx]})
    })
  }, [radioList])



// 3) Declare "toggle()" to modify the list that keeps track of what indexes are active

  const toggle = (targetIndex) => {

    let newList = radioList.map((item, idx) => {
      if (allowMultiple) {
        return targetIndex == idx ? !item : item
      } else {
        return targetIndex == idx ? !item : false
      }
    })
    setRadioList(newList)
  }

  return toggle
}

// expected:  const toggle = useRadioList(children)

当我调用toggle时,会出现以下错误:

警告:来自useState()和useReucer()钩子的状态更新不支持第二个回调参数。若要在呈现后执行副作用,请在组件主体中使用use效应()声明副作用。

编辑:

setRadioList(…新列表)----

不再获得回调错误,现在我似乎很难有效地将状态映射到子级,因为isExpanded属性在初始渲染后不会显示在每个子级中。


共有2个答案

李锦
2023-03-14

setRadioList必须这样使用:

setRadioList(newList)

Spread运算符拆分数组并将每个值作为单独的参数发送,因此,例如,setRadioList(…[1,2,3])将变成setRadioList(1,2,3),这当然是不正确的。

看见https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_array_literals

陶烨赫
2023-03-14

操作子级的代码不会改变原来的子级,而是创建新的子级,所以下面的代码没有任何效果:

   Children.map(children, (child, idx) => {
      if (!isValidElement(child)) {return}

      return cloneElement(child, {isExpanded: radioList[idx]})
    });

尝试返回新的子对象,如下所示:

export default (originalChildren, allowMultiple = true) => {


  // 1) Setup initial list 

    const [radioList, setRadioList] = useState(Array(originalChildren.length).fill(false))
    const [children, setChildren] = useState(originalChildren);

  // 2) Map radioList values to component children on initial render, and do so again if radioList changes

    useEffect(() => {
      setChildren(children => Children.map(children, (child, idx) => {
        if (!isValidElement(child)) {return}

        return cloneElement(child, {isExpanded: radioList[idx]})
      }));

    }, [radioList])



  // 3) Declare "toggle()" to modify the list that keeps track of what indexes are active

    const toggle = useCallback((targetIndex) => {
      setRadioList(radioList => radioList.map((item, idx) => {
        if (allowMultiple) {
          return targetIndex == idx ? !item : item
        } else {
          return targetIndex == idx ? !item : false
        }
      }))
    }, [allowMultiple])

    return { toggle, children }
  }

  // use like this:  const { toggle, children } = useRadioList(children)
 类似资料:
  • 问题:在函数“selectmenu”中调用了React钩子“React.useEffect”,该函数既不是React函数组件,也不是自定义React钩子函数 目标:我只想在单击按钮时挂载组件('Component DidMount/WillUnmount)(使用useffect()),而不是在加载文件(或整个组件)时挂载 实际目标:我想在单击时选择(或突出显示)一个文件(自定义)。但是,当用户在文

  • 我试图在一个功能组件中调用一个API,它是一个反应挂钩,并基于结果,重新呈现组件的内容。下面是代码: 调用API的组件- 以下是功能: 我正在尝试获取状态数据,并根据数据重新渲染组件。这里处于调用外部API的操作中。 正在调用操作并成功获取数据,但我不确定为什么状态正在更新-我得到了以下错误- 在函数“setResults”中调用React钩子“useState”,该函数既不是React函数组件,

  • 我不熟悉react钩子和功能组件,我正在尝试在我的功能组件中使用useState,它会向我显示前面提到的错误 使用React、ant设计 参考以下输入链接描述在这里 错误: 在函数“deviceStatus”中调用React钩子“useState”,该函数既不是React函数组件,也不是自定义React钩子函数React钩子/钩子规则

  • 我正在跟随一个关于Udemy的反应课程。现在我达到了我的代码的这一点 编译后,我遇到了这个错误消息,我不知道该怎么做或意思

  • 我发现自己处于一种奇怪的境地。我正在实现一个钩子,我无法实现我想要的。 我有这样的想法: 我的问题是函数setFoo正确执行,所以foo state是一个新的数组,但是setBar依赖于foo的状态,接收一个空数组。基本上setBar是在setFoo完成之前执行的,所以getBar函数接收一个空数组。 管理这种依赖的正确方法是什么? 谢谢F

  • 问题内容: 我目前正在阅读John Papa的AngularJS样式指南,并看到了以下代码: 您可以看到函数和是 在 函数返回值 之后 定义的。这是如何运作的?它是否符合标准并且可以在所有浏览器中使用(例如,来自IE 6)? 问题答案: 您可以看到函数和是在函数返回值之后定义的。 那是从它们的编写位置看的样子,是的,但是实际上它们是在函数中的任何分步代码完全运行之前定义的。有时这被称为“提升”函数