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

如何为useParamsData Hook自动推导不同组件initData的类型?

问题描述

当不同组件向useParamsData Hook传入结构不同的initData时,能否为Hook的参数传递类型,并将其指定为params的类型?

目前的手动方案需要为每个组件的initData定义类型,再手动添加联合类型到Hook的参数中,新增组件时十分繁琐,希望替代这种方案。

useParamsData Hook用于在事件触发时将各类数据存入params,避免重复编写change/onclick等逻辑。已知useState可通过泛型指定初始数据类型,但在Jotai Atom中难以实现,特此寻求解决方案。


原始代码示例

useParams.ts

import { useEffect, useState } from 'react';

export const useParamsData = (initData) => {
  const [params, setChangeParams] = useState({});

  useEffect(() => {
    setChangeParams(initData);
  }, []);
  return {
    params,
    setChangeParams,
  };
};

ComponentA.tsx

import { useState } from 'react';
import { useParamsData } from './useParamsData';
import './style.css';

export const ComponentA = () => {
  const initData = {
    age: 0,
    name: 'jhon',
    county: '',
  };
  const { params, setChangeParams } = useParamsData(initData);
  return (
    <div>
      <p>Start editing to see some magic happen :)</p>
    </div>
  );
};

ComponentB.tsx

import { useState } from 'react';
import { useParamsData } from './useParamsData';
import './style.css';

export const ComponentB = () => {
    const initData = {
    category: 'All',
    status: 'All',
    type: 'All',
    module: 'All',
    keword: '',
    startDate: '',
    endDate: '',
  };
  const { params, setChangeParams } = useParamsData(initData);
  return (
    <div>
      <p>Start editing to see some magic happen :)</p>
    </div>
  );
};

需替代的手动方案

--- useParams.ts---

import { useEffect, useState } from 'react';

type A = {
  age: string
  name: string
  county: string,
}
type B = {
  category: string
  status: string
  type: string
  module: string
  keword : string
  startDate: string
}

export const useParamsData = (initData : A | B) => {
  const [params, setChangeParams] = useState({});

  useEffect(() => {
    setChangeParams(initData);
  }, []);
  return {
    params,
    setChangeParams,
  };
};

解决方案:用泛型实现动态类型推导

React 版本

给useParamsData添加泛型,让TypeScript自动推导initData的类型,无需手动维护联合类型:

import { useState } from 'react';

export const useParamsData = <T extends Record<string, unknown>>(initData: T) => {
  // 直接用initData初始化useState,泛型T自动绑定类型
  const [params, setChangeParams] = useState<T>(initData);

  // 原代码的useEffect多余,因为useState已用initData初始化
  return { params, setChangeParams };
};

组件调用时,TypeScript会自动推导params的类型:

  • ComponentA中params类型为{ age: number; name: string; county: string }
  • ComponentB中params类型为{ category: string; status: string; type: string; module: string; keword: string; startDate: string; endDate: string }

Jotai Atom 版本

通过泛型函数生成对应类型的Atom,解决Jotai中动态类型的问题:

import { atom, useAtom } from 'jotai';

// 泛型函数生成指定类型的Atom
export const createParamsAtom = <T extends Record<string, unknown>>(initData: T) => {
  return atom<T>(initData);
};

// 组件内使用示例
export const ComponentA = () => {
  const initData = { age: 0, name: 'jhon', county: '' };
  const paramsAtom = createParamsAtom(initData);
  const [params, setParams] = useAtom(paramsAtom);

  return <div>{/* 组件内容 */}</div>;
};

如果需要跨组件共享Atom,可通过类型断言指定具体类型:

import { atom, useAtom } from 'jotai';

// 基础共享Atom
export const paramsAtom = atom<Record<string, unknown>>({});

// 组件内使用时指定类型
export const ComponentA = () => {
  type ParamsType = { age: number; name: string; county: string };
  const [params, setParams] = useAtom<ParamsType>(paramsAtom);

  setParams({ age: 25, name: 'John', county: 'USA' });
  return <div>{params.name}</div>;
};

内容的提问来源于stack exchange,提问作者김찬영

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 19:45:12