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

使用useReducer时Kendo React Grid无法进入单元格编辑的问题咨询

Kendo React Grid 结合 useReducer 实现单元格编辑与排序示例

核心问题在于使用useReducer时,必须保证状态更新的不可变性——Kendo Grid依赖状态的引用变化触发重新渲染,直接修改原状态会导致Grid无法感知到变化,从而无法进入编辑模式。以下是完整的实现示例,包含单元格编辑、排序功能:

完整代码实现

import { useReducer } from 'react';
import { Grid, GridColumn } from '@progress/kendo-react-grid';
import { process } from '@progress/kendo-data-query';

// 定义reducer的action类型
const ACTION_TYPES = {
  START_EDIT: 'START_EDIT',
  UPDATE_CELL: 'UPDATE_CELL',
  END_EDIT: 'END_EDIT',
  SORT: 'SORT'
};

// 状态初始化
const initialState = {
  data: [
    { id: 1, name: 'John Doe', age: 30, email: 'john@example.com' },
    { id: 2, name: 'Jane Smith', age: 25, email: 'jane@example.com' },
    { id: 3, name: 'Bob Brown', age: 35, email: 'bob@example.com' }
  ],
  editField: '',
  sort: [],
  editedItem: null
};

// reducer函数,处理所有状态更新逻辑
function gridReducer(state, action) {
  switch (action.type) {
    case ACTION_TYPES.START_EDIT:
      return {
        ...state,
        editedItem: action.payload.item,
        editField: action.payload.field
      };
    case ACTION_TYPES.UPDATE_CELL:
      // 不可变更新数据:创建新数组,替换修改后的项
      const updatedData = state.data.map(item =>
        item.id === action.payload.item.id
          ? { ...item, [action.payload.field]: action.payload.value }
          : item
      );
      return {
        ...state,
        data: updatedData,
        editedItem: { ...action.payload.item, [action.payload.field]: action.payload.value }
      };
    case ACTION_TYPES.END_EDIT:
      return {
        ...state,
        editedItem: null,
        editField: ''
      };
    case ACTION_TYPES.SORT:
      return {
        ...state,
        sort: action.payload.sort
      };
    default:
      return state;
  }
}

export default function GridWithReducer() {
  const [state, dispatch] = useReducer(gridReducer, initialState);

  // 处理单元格点击,进入编辑模式
  const handleCellClick = (event) => {
    if (event.dataItem && event.field) {
      dispatch({
        type: ACTION_TYPES.START_EDIT,
        payload: { item: event.dataItem, field: event.field }
      });
    }
  };

  // 处理单元格内容变化
  const handleChange = (event) => {
    dispatch({
      type: ACTION_TYPES.UPDATE_CELL,
      payload: {
        item: state.editedItem,
        field: event.target.name,
        value: event.target.value
      }
    });
  };

  // 处理编辑结束(比如失去焦点)
  const handleBlur = () => {
    dispatch({ type: ACTION_TYPES.END_EDIT });
  };

  // 处理排序变化
  const handleSortChange = (event) => {
    dispatch({
      type: ACTION_TYPES.SORT,
      payload: { sort: event.sort }
    });
  };

  // 使用kendo-data-query的process函数处理排序后的数据
  const processedData = process(state.data, {
    sort: state.sort
  }).data;

  // 自定义编辑单元格渲染
  const renderEditCell = (props) => {
    if (props.dataItem === state.editedItem && props.field === state.editField) {
      return (
        <td>
          <input
            name={props.field}
            value={props.dataItem[props.field]}
            onChange={handleChange}
            onBlur={handleBlur}
            autoFocus
          />
        </td>
      );
    }
    return <td>{props.dataItem[props.field]}</td>;
  };

  return (
    <Grid
      data={processedData}
      onCellClick={handleCellClick}
      sortable={true}
      onSortChange={handleSortChange}
      sort={state.sort}
    >
      <GridColumn field="name" title="Name" cell={renderEditCell} />
      <GridColumn field="age" title="Age" cell={renderEditCell} />
      <GridColumn field="email" title="Email" cell={renderEditCell} />
    </Grid>
  );
}

关键要点说明

  • 不可变状态更新:在reducer中修改数据时,始终创建新的数组/对象(如state.data.map、{ ...item }),绝对不能直接修改原状态对象,否则Grid无法检测到变化。
  • 编辑状态管理:通过editedItem和editField跟踪当前编辑的单元格,点击单元格时触发START_EDIT action,更新时触发UPDATE_CELL,失去焦点时触发END_EDIT。
  • 排序集成:将排序状态存入reducer,通过handleSortChange更新排序配置,使用process函数处理数据排序,确保排序后的数据正确渲染。
  • 自定义单元格渲染:通过cell属性自定义单元格,判断当前单元格是否处于编辑状态,渲染输入框或普通文本。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 17:32:02