如何在TypeScript的React自定义Hook中传参?解决TS2345报错
问题:调用自定义Hook传递字符串时出现TypeScript类型错误
我尝试在调用自定义Hook时传入一个字符串(比如指定JSON文件路径)来获取对应数据,但即使定义了Prop类型,还是报错:TS2345: Argument of type 'string' is not assignable to parameter of type '{ string: any; }',这是为什么?
1. 自定义Hook代码
import axios from 'axios'; import React, { FC } from 'react'; import { useState, useEffect } from 'react' interface APICallProps { apiCall: string } const useFetchSecurityData = ({ string: apiCall }) => { const [loading, setLoading] = useState<boolean>(true) const [data, setData] = useState<null>(null) useEffect(() => { fetchData() }, []) const fetchData = async () => { axios.get(apiCall) .then(res => { setData(res.data) }) .catch(err => console.error(err)) setLoading(false) } return { data, loading } } export default useFetchSecurityData
2. 页面中调用Hook的代码
const ChartArea = () => { const [incidents, setIncidents] = useState([]) const { data, loading } = useFetchSecurityData('incidents.json') // const { data, loading } = useFetchIncidents() useEffect(() => { fetchData() }, [loading, data]) const fetchData = () => { try { let rawData = (data) ?? [] setIncidents(rawData) } catch (err) { console.error(err) } } }
原因及修复方案
错误原因
你的自定义Hook useFetchSecurityData 参数定义存在矛盾:
- 你声明了接口
APICallProps包含apiCall字符串字段,但实际函数参数用了对象解构的错误写法{ string: apiCall },这意味着Hook期望接收一个包含string属性的对象,而非直接传入字符串。 - 但调用时你传的是原始字符串
'incidents.json',TypeScript自然会报类型不匹配错误。
修复步骤
根据需求,有两种修复方式:
方式一:让Hook接收对象参数(匹配定义的APICallProps接口)
- 修正Hook的参数解构,对齐接口字段:
// 把 { string: apiCall } 改成 { apiCall },对应APICallProps的字段 const useFetchSecurityData = ({ apiCall }: APICallProps) => { // ... 其余代码不变 }
- 调用Hook时传入对象:
const { data, loading } = useFetchSecurityData({ apiCall: 'incidents.json' })
方式二:让Hook直接接收字符串参数(更简洁)
如果不需要传递多个参数,直接让Hook接收字符串即可:
- 修改Hook的参数定义:
// 去掉APICallProps接口,直接定义参数为string类型 const useFetchSecurityData = (apiCall: string) => { // ... 其余代码不变 }
- 调用方式保持不变:
const { data, loading } = useFetchSecurityData('incidents.json')
额外优化点
你的fetchData函数存在逻辑问题:setLoading(false)写在axios请求外部,会导致请求未完成就将loading设为false,建议调整为:
const fetchData = async () => { try { const res = await axios.get(apiCall) setData(res.data) } catch (err) { console.error(err) } finally { setLoading(false) } }
内容的提问来源于stack exchange,提问作者Tyler Morales
相关产品推荐
相关产品推荐

