[英]Having trouble returning function in custom React hook
我目前正在尝试创建一个useRadioList()
挂钩来跟踪给定组件中所有子级的isExpanded
道具(当一个子级切换isExpanded
时,其他子级取消切换)
我这样做的方法是:
isExpanded
道具// 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)
当我调用切换时,我收到以下错误:
警告:State 更新来自 useState() 和 useReducer() Hooks 不支持第二个回调参数。 要在渲染后执行副作用,请在组件主体中使用 useEffect() 声明它。
编辑:
setRadioList(...newList) ----> setRadioList(newList)
不再收到callback
错误,现在我似乎无法有效地将 state 映射到孩子,因为在初始渲染后,每个孩子中都没有显示isExpanded
道具。
setRadioList
必须像这样使用:
setRadioList(newList)
扩展运算符拆分数组并将每个值作为单独的参数发送,因此例如setRadioList(...[1,2,3])
将变为setRadioList(1, 2, 3)
这当然是不正确的。
操作孩子的代码,不会改变原来的孩子,而是创建一个新的,所以下面的代码没有效果:
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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.