【问题标题】:Grid of Refs in typescript打字稿中的参考网格
【发布时间】:2021-05-22 09:03:20
【问题描述】:

我正在尝试在 React 打字稿中创建一个网格,想要访问每个节点内带有 refs 的节点我正在使用 useImperativeHandle 返回一个函数和节点状态

const Grid: React.FC<PropsType> = (props) => {
    const makeGrid = (): void => {
        const newGrid: gridNode[][] = []
        for (let i = 0; i < HIEGHT; i++) {
            const gridRow: gridNode[] = []
            for (let j = 0; j < WIDTH; j++) {
                const node: gridNode = {
                    row: i,
                    col: j,
                    ref: React.createRef<NodeHandle>()
                }
                gridRow.push(node)
            }
            newGrid.push(gridRow)
        }
        setGrid(newGrid)
    }

    useEffect(() => { makeGrid() }, [])
    
    return (
         <>
            {grid.forEach(row => {
                 return (<>
                      {row.forEach(node => {
                          <Node ref = {node.ref} />
                       })
                 </>)
            })
         </>
    )
}

我想使用 useRef() 钩子使其更内联我正在使用的功能组件,我不知道将 refs 放在状态对象中是否是最佳做法

const Node: React.ForwardRefRenderFunction<NodeHandle, NodeProps> = (props, ref) => {
       
        changeStatus = (newStatus: string) => {
             //changes the status
        }
        useImperativeHandle(ref, () => {
            return {
               changeStatus,
               status,
        }
    })
    return (
      <div>Node</div>
    )
}

我对 typeScript 很陌生,以前也没有使用过这么多的 refs

【问题讨论】:

    标签: reactjs typescript react-hooks react-ref


    【解决方案1】:

    forEach() 不返回任何内容。在循环节点时需要使用.map()

    React.ForwardRefRenderFunction 不是 Node 组件的正确类型。那就是描述forwardRef的内部函数inside的类型。但你实际上并没有在任何地方打电话给forwardRef。你想要:

    const Node = forwardRef<NodeHandle, NodeProps>((props, ref) => {
    

    useImperativeHandle 通常不需要。最好将状态提升到父级。

    您从每个节点获得的信息似乎是它的status 和一个用于更改该状态的回调。您可以将状态状态向上移动到 Grid 组件中,并将这两个值作为道具向下传递给 Node

    我明白为什么与在二维数组中进行更新相比,基于 ref 的方法看起来更有吸引力。所以也许重新考虑一下你的州的形状更平坦?

    const Node = ({status, changeStatus}: NodeProps) => {
        return (
            <div>Node</div>
        )
    };
    
    const Grid: React.FC<PropsType> = (props) => {
    
        const initialStatus = "initial";
    
        /**
         * Store a partial object of node statuses keyed by the key for each node.
         * Formulate each key as "row-column".
         * Assume that any key which isn't present has the initial value.
         * This allows you to avoid creating an object of initial states.
         */
        const [keyedStatuses, setKeyedStatuses] = useState<Partial<Record<string, string>>>({});
    
        /**
         * Iterate through all row indexes and column indexes.
         * The arrays are filled with `undefined`, so 
         * skip the value and just use the index.
         */
        return (
            <>
                {Array.from({length: HEIGHT}).map((_, i) =>
                    Array.from({length: WIDTH}).map((_, j) => {
                        const key = `${i}-${j}`;
                        return (
                            <Node
                                key={key}
                                // get the current status
                                status={keyedStatuses[key] ?? initialStatus}
                                // update the status for just this node
                                changeStatus={(newStatus: string) => setKeyedStatuses(
                                    prevState => ({
                                        ...prevState,
                                        [key]: newStatus
                                    })
                                )}
                            />
                        )
                    })
                )}
            </>
        )
    };
    

    【讨论】:

    • 一切都如你所说,只是我经常改变状态,这就是为什么我需要 refs 不再渲染整个网格而只是重新渲染节点
    猜你喜欢
    • 1970-01-01
    • 2016-06-06
    • 2012-12-09
    • 2015-08-13
    • 1970-01-01
    • 1970-01-01
    • 2021-09-20
    • 2020-03-18
    • 1970-01-01
    相关资源
    最近更新 更多