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

如何在Redux切片文件中调用组件内定义的函数?

问题解决方案

核心问题是你不应该在Redux状态中存储React元素——Redux的设计初衷是存储可序列化的纯数据,而非包含组件闭包引用的UI元素。下面是具体的修正方案:


1. 修改Redux Thunk:只返回纯数据

把原来在thunk里生成<i>标签的逻辑去掉,仅返回API数据和操作标识,让UI层负责渲染交互元素:

export const getNomads = createAsyncThunk("applicant/getNomads", async(data) => {
  const { searchParam, pageNum } = data;

  let nomadObj = {
    isPending: true,
    bodyArray: []
  };

  const response = await axios.get(`https://demo.khedmatashayer-kj.ir/api/v1/nomad/${pageNum}?${searchParam}`, config);
  
  if (response.data) {
    const array = response.data.map((item) => {
      // 仅存储数据和操作类型标识,不生成React元素
      return [
        { type: 'edit', data: item },
        { type: 'history', data: { name: item.name, nomadId: item.nomad_id } },
        // 原有的其他数据字段...
        item.name,
        item.nomad_id,
        // ...其他需要展示的字段
      ];
    });
    nomadObj = {
      isPending: false,
      bodyArray: array
    };
  }

  return nomadObj;
});

2. 通过Context传递事件处理函数

因为UserInformationTable是MyComponent的后代组件,用React Context跨层级传递操作函数,避免props层层传递:

第一步:创建操作Context

// TableActionsContext.js
import { createContext, useContext } from 'react';

const TableActionsContext = createContext({
  handleShowForm: () => {},
  handleShowHistory: () => {},
});

export const useTableActions = () => useContext(TableActionsContext);
export default TableActionsContext;

第二步:在MyComponent中提供Context

import TableActionsContext from './TableActionsContext';

const MyComponent = () => {
  const handleShowForm = (arg) => {
    // 你的原逻辑
  };

  const handleShowHistory = (arg1, arg2) => {
    // 你的原逻辑
  };

  useEffect(() => {
    dispatch(getNomads({
      searchParam: '',
      pageNum: 1 // 修正原代码的拼写错误:pagaNum → pageNum
    }));
  }, []); // 添加依赖数组,避免无限循环

  return (
    <TableActionsContext.Provider value={{ handleShowForm, handleShowHistory }}>
      {/* 渲染UserInformationTable或其上层组件 */}
      <UserInformationTable />
    </TableActionsContext.Provider>
  );
};

3. 在表格组件中渲染交互元素

修改UserInformationTable,根据纯数据渲染按钮并绑定Context提供的事件函数:

import { useTableActions } from './TableActionsContext';

const UserInformationTable = () => {
  const { headArray, bodyArray, searchedBodyArray, statusStyle } = useContext(MyContext);
  const { handleShowForm, handleShowHistory } = useTableActions();
  const data = searchedBodyArray?.length > 0 ? searchedBodyArray : bodyArray;
  const isPending = useSelector(selectIsPending);

  // 统一处理单元格内容渲染
  const renderCell = (entry) => {
    if (entry.type === 'edit') {
      return (
        <i 
          className="fa fa-edit edit"
          onClick={() => handleShowForm(entry.data)}
        ></i>
      );
    }
    if (entry.type === 'history') {
      return (
        <i 
          className="fa fa-file-text-o records"
          onClick={() => handleShowHistory(entry.data.name, entry.data.nomadId)}
        ></i>
      );
    }
    // 普通数据直接返回
    return entry;
  };

  return (
    <table className='user-table'>
      <thead>
        <tr>
          {headArray.map((item, index) => (
            <th key={index}>{item}</th>
          ))}
        </tr>
      </thead>
      {isPending ? (
        <tbody>
          <tr><td colSpan='100'><Loading /></td></tr>
        </tbody>
      ) : (
        <tbody>
          {(data?.length === 0 || data[0] === 'موردی یافت نشد') ? (
            <tr><td className='empty-table' colSpan='100%'>موردی یافت نشد</td></tr>
          ) : (
            data?.map((item, index) => (
              <tr key={index}>
                {item.map((entry, index1) => (
                  <td 
                    key={index1} 
                    className='table-entry' 
                    style={index1 === 12 ? statusStyle[index] : {}}
                  >
                    {renderCell(entry)}
                  </td>
                ))}
                <td>{toFarsiNumber(index + 1)}</td>
              </tr>
            ))
          )}
        </tbody>
      )}
    </table>
  );
};

方案优势

  • 符合Redux设计原则:状态只存纯数据,避免序列化问题和闭包引用导致的意外bug
  • 职责分离:数据获取层(thunk)只负责拿数据,UI层负责渲染交互逻辑
  • 灵活扩展:其他不需要操作按钮的组件,只需不提供TableActionsContext或传入空函数即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 05:05:02