You need to enable JavaScript to run this app. React.js中如何复用函数与useState变量 避免重复复制粘贴代码?
优惠活动
大模型
产品
解决方案
定价
更多

React.js中如何复用函数与useState变量 避免重复复制粘贴代码?

React重复逻辑复用解决方案

你遇到的这类状态、处理函数、计算逻辑完全一致的重复场景,在React中可以通过以下两种方案实现复用,无需复制粘贴代码:

方案1:自定义Hook(仅复用逻辑首选)

自定义Hook是React专门用于抽离可复用状态逻辑的方案,你可以把所有重复的逻辑封装到一个以use开头的函数中,需要使用时直接调用即可,每次调用都会生成完全独立的状态,互不干扰。

封装自定义Hook代码示例

import { useState } from 'react';
// 替换为你实际引用图表组件的路径
import { Line, Bar, Pie, Radar, Doughnut, Scatter, PolarArea, Bubble } from 'chart.js/react';

const useChart = () => {
  const [title, setTitle] = useState("");
  const [state, setState] = useState({});
  const [getId, setGetId] = useState([]);
  const [info, setInfo] = useState([]);

  const clickCheck = title => e => {
    setState({
      ...state,
      [title]: [e.currentTarget.value],
    });
    // 修正原代码直接修改state的不规范写法,所有state修改走setter函数
    const newIdArr = [...getId, e.currentTarget.id];
    setGetId(newIdArr.length > 2 ? [] : newIdArr);
  };

  const axis = getId.length >= 2 ? [
    info.map(i => i[getId[0]]).slice(1),
    info.map(i => i[getId[1]]).slice(1),
  ] : [[], []];

  const chartData = {
    labels: axis[0],
    datasets: [
      {
        label: title,
        data: axis[1],
        backgroundColor: [
          "rgba(255, 99, 132, 1)",
          "rgba(54, 162, 235, 1)",
          "rgba(255, 206, 86, 1)",
          "rgba(75, 192, 192, 1)",
          "rgba(153, 102, 255, 1)",
          "rgba(255, 159, 64, 1)",
        ],
      },
    ],
  };

  const chartArray = [
    <Line key="o" data={chartData} options={{ responsive: true, maintainAspectRatio: false }} />,
    <Bar key="p" data={chartData} options={{ responsive: true, maintainAspectRatio: false }} />,
    <Pie key="q" data={chartData} options={{ responsive: true, maintainAspectRatio: false }} />,
    <Radar key="r" data={chartData} options={{ responsive: true, maintainAspectRatio: false }} />,
    <Doughnut key="s" data={chartData} options={{ responsive: true, maintainAspectRatio: false }} />,
    <Scatter key="t" data={chartData} options={{ responsive: true, maintainAspectRatio: false }} />,
    <PolarArea key="u" data={chartData} options={{ responsive: true, maintainAspectRatio: false }} />,
    <Bubble key="v" data={chartData} options={{ responsive: true, maintainAspectRatio: false }} />,
  ];

  return {
    title, setTitle,
    state, setState,
    getId, setGetId,
    info, setInfo,
    clickCheck,
    axis,
    chartData,
    chartArray
  }
}

组件内使用示例

const YourBusinessComponent = () => {
  // 生成第一组图表逻辑
  const {
    title: title1,
    setTitle: setTitle1,
    info: info1,
    setInfo: setInfo1,
    clickCheck: clickCheck1,
    chartArray: chartArray1
  } = useChart();

  // 生成第二组图表逻辑
  const {
    title: title2,
    setTitle: setTitle2,
    info: info2,
    setInfo: setInfo2,
    clickCheck: clickCheck2,
    chartArray: chartArray2
  } = useChart();

  // 需要更多组逻辑直接重复调用useChart即可
  return (
    // 你的业务UI代码,按需使用上面返回的状态和方法
  )
}

方案2:封装独立组件(逻辑+UI一起复用首选)

如果每组逻辑对应的UI结构也完全一致,你可以直接把逻辑和UI一起封装成独立的业务组件,需要多少组就渲染多少个组件即可。

封装组件示例

const ChartGroup = () => {
  // 直接复用上面定义的useChart
  const { title, setTitle, info, setInfo, clickCheck, chartArray } = useChart();

  return (
    <div className="chart-group-wrap">
      {/* 替换为你每组图表对应的UI结构 */}
      <input 
        value={title} 
        onChange={(e) => setTitle(e.target.value)} 
        placeholder="输入图表标题" 
      />
      <div className="chart-list">
        {chartArray.map(ChartItem => ChartItem)}
      </div>
    </div>
  )
}

组件内使用示例

const YourBusinessComponent = () => {
  return (
    <div>
      <ChartGroup />
      <ChartGroup />
      {/* 需要多少组就渲染多少个ChartGroup */}
    </div>
  )
}

注意事项

  • 原代码中直接修改state(getId = [])的写法不符合React规范,所有state的修改都必须通过对应的setter函数实现,避免出现状态不同步的问题,上述代码已经修正了该问题
  • 可以给自定义Hook或封装的组件增加props参数,支持传入个性化配置(比如自定义背景色、图表尺寸等),灵活适配不同场景的需求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.14 08:15:07