You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Render Prop模式下如何实现子组件回调并向渲染props传参?

解决Render Prop模式下子组件操作传递问题

核心思路

要捕获ColumnAction内部的宽度调整、列重排等操作并通知父组件,关键是让ColumnAction在内部操作触发状态/属性变更时,把变更信息通过Render Prop的参数暴露出来,父组件在渲染回调里接收这些参数后,就能调用主组件的对应操作。

步骤1:改造ColumnAction组件

在ColumnAction内部,处理mouseDown/mouseUp等事件导致列属性变化时,把需要传递的信息(比如列标识、新宽度、操作类型)合并到传给Render Prop的参数中。示例如下:

// ColumnAction.jsx
import { useState, useRef, useEffect } from 'react';

const ColumnAction = ({ children, columnKey }) => {
  const [columnWidth, setColumnWidth] = useState(180); // 初始宽度
  const ref = useRef(null);
  const ref2 = useRef(null);
  let startX = 0;
  let startWidth = 0;

  // 处理列宽度调整逻辑
  const handleMouseDown = (e) => {
    startX = e.clientX;
    startWidth = ref2.current.offsetWidth;
    document.addEventListener('mousemove', handleMouseMove);
    document.addEventListener('mouseup', handleMouseUp);
  };

  const handleMouseMove = (e) => {
    const newWidth = startWidth + (e.clientX - startX);
    setColumnWidth(newWidth);
  };

  const handleMouseUp = () => {
    document.removeEventListener('mousemove', handleMouseMove);
    document.removeEventListener('mouseup', handleMouseUp);
  };

  useEffect(() => {
    if (ref.current) {
      ref.current.addEventListener('mousedown', handleMouseDown);
    }
    return () => {
      if (ref.current) {
        ref.current.removeEventListener('mousedown', handleMouseDown);
      }
    };
  }, []);

  // 把ref、ref2和变更信息一起传给render函数
  return children({
    ref,
    ref2,
    columnWidth,
    columnKey,
    operationType: 'resize' // 标识操作类型,方便父组件区分
  });
};

export default ColumnAction;

步骤2:在父组件中接收参数并触发主组件操作

修改你现有的TableHead代码,在Render Prop的回调里接收新增的参数,通过useEffect监听属性变化,触发主组件传入的回调方法:

const TableHead = props.selectedAttributes.map(attribute => {
  const attributeDetail = props.attributes.find(attr => attr.attribute === attribute);
  
  return (
    <ColumnAction key={attribute} columnKey={attribute}>
      {({ ref, ref2, columnWidth, columnKey }) => {
        // 监听列宽度变化,通知主组件
        useEffect(() => {
          props.onColumnChange({
            key: columnKey,
            width: columnWidth,
            type: 'resize'
          });
        }, [columnWidth, columnKey, props.onColumnChange]);

        return (
          <th 
            className='UniveralGridTableHead draggable' 
            data-attrb={attribute} 
            data-menu={props.menu} 
            ref={ref2}
            style={{ width: `${columnWidth}px` }} // 应用调整后的宽度
          >
            {attributeDetail.label}
            <i
              className='sortDesc'
              style={{
                display: attributeDetail.sortable ? 'inline-block' : 'none',
                borderTop: props.orderBy === attribute && props.orderDirection === 'DESC' ? '5px solid #EEEEEE' : '5px solid #888888'
              }}
              onClick={() => props.conditionCallback('sortDesc', attribute)}
            ></i>
            <i
              className='sortAsc'
              style={{
                display: attributeDetail.sortable ? 'inline-block' : 'none',
                borderBottom: props.orderBy === attribute && props.orderDirection === 'ASC' ? '5px solid #EEEEEE' : '5px solid #888888'
              }}
              onClick={() => props.conditionCallback('sortAsc', attribute)}
            ></i>
            <div className='ColumnResizer' ref={ref}></div>
          </th>
        );
      }}
    </ColumnAction>
  );
});

步骤3:主组件中处理回调

在主组件里定义onColumnChange方法,接收子组件传来的变更信息,触发后续操作:

const MainTable = () => {
  const handleColumnChange = (changeInfo) => {
    // 根据变更信息执行对应逻辑,比如更新列配置缓存、触发表格数据重新渲染等
    console.log(`列${changeInfo.key}宽度变为${changeInfo.width}px`);
    // 这里可以调用其他需要触发的业务操作
  };

  return (
    <table>
      <thead>
        {TableHead({
          selectedAttributes: ['id', 'name', 'age'],
          attributes: [...],
          conditionCallback: (...args) => {},
          onColumnChange: handleColumnChange // 传入回调方法
        })}
      </thead>
      <tbody>...</tbody>
    </table>
  );
};

额外说明

如果ColumnAction里的操作(比如列重排)不是状态驱动的,也可以直接在操作完成时调用props传入的回调,比如给ColumnAction加一个onReorder属性,内部重排完成后直接调用props.onReorder(columnKey, newPosition),这种方式更直接。

内容的提问来源于stack exchange,提问作者Maker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 23:43:24