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

如何实现React Native通用可配置选项数的N选自定义Hook?

通用N选自定义Hook实现方案

核心思路

将选项总数/选项列表作为入参传入Hook,动态生成对应数量的切换函数,无需为不同选项数单独编写专用Hook,同时保持和原有使用习惯的兼容性。

基础版本实现(按选项总数生成,返回索引)

完全兼容你原有useTripleSelection的调用习惯,仅需传入选项总数即可适配任意N选场景:

import { useCallback, useState, useMemo } from 'react';

export const useSelection = (total: number, defaultValue = 0) => {
  if (total < 1) throw new Error('选项总数 total 必须大于等于1');
  const [value, setValue] = useState(defaultValue);

  // 批量生成对应索引的切换函数
  const toggles = useMemo(() => {
    return Array.from({ length: total }, (_, index) => () => setValue(index));
  }, [total]);

  // 额外提供通用设置方法,支持直接传索引修改,适配更灵活的场景
  const setSelection = useCallback((newValue: number) => {
    if (newValue >= 0 && newValue < total) setValue(newValue);
  }, [total]);

  return [value, toggles, setSelection] as const;
};

使用示例

// 原3选场景,用法和之前完全对齐
const [selected, [toggleZero, toggleOne, toggleTwo]] = useSelection(3);

// 2选场景
const [selected, [toggleOn, toggleOff]] = useSelection(2);

// 4选场景
const [selected, toggles] = useSelection(4);
// 调用时直接使用 toggles[0]、toggles[1] 即可

增强版本实现(支持任意类型选项值)

如果你的选项值不是数字索引,而是字符串、对象等类型,可以使用增强版本,直接传入选项列表即可:

import { useCallback, useState, useMemo } from 'react';

export const useSelection = <T,>(options: T[], defaultValue?: T) => {
  if (options.length < 1) throw new Error('选项数组不能为空');
  const [value, setValue] = useState<T>(defaultValue ?? options[0]);

  const toggles = useMemo(() => {
    return options.map(option => () => setValue(option));
  }, [options]);

  const setSelection = useCallback((newValue: T) => {
    if (options.includes(newValue)) setValue(newValue);
  }, [options]);

  return [value, toggles, setSelection] as const;
};

使用示例

// 性别选择场景,直接传入选项值
const [gender, [selectMale, selectFemale, selectUnknown]] = useSelection(['男', '女', '不愿透露']);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 01:54:02