Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/422.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何键入自定义钩子useStateWithCallback React-TypeScript_Javascript_Reactjs_Typescript_React Hooks - Fatal编程技术网

Javascript 如何键入自定义钩子useStateWithCallback React-TypeScript

Javascript 如何键入自定义钩子useStateWithCallback React-TypeScript,javascript,reactjs,typescript,react-hooks,Javascript,Reactjs,Typescript,React Hooks,我在键入以下自定义Reacthook时遇到问题,我是TypeScript新手,这会造成一些混乱 const useStateCallback = (initialState: any) => { const [state, setState] = useReducer<Reducer<any, any>>((state, newState) => ({ ...state, ...newState }), initialState) const cbRe

我在键入以下自定义React
hook
时遇到问题,我是TypeScript新手,这会造成一些混乱

const useStateCallback = (initialState: any) => {
  const [state, setState] = useReducer<Reducer<any, any>>((state, newState) => ({ ...state, ...newState }), initialState)
  const cbRef = useRef(null)

  const setStateCallback = (state, cb) => {
    cbRef.current = cb
    setState(state)
  }

  useEffect(() => {
    if (cbRef.current) {
      cbRef.current(state)
      cbRef.current = null
    }
  }, [state])

  return [state, setStateCallback]
}
const useStateCallback=(initialState:any)=>{
const[state,setState]=useReducer((state,newState)=>({…state,…newState}),initialState)
const cbRef=useRef(空)
常量setStateCallback=(状态,cb)=>{
cbRef.current=cb
设置状态(状态)
}
useffect(()=>{
if(cbRef.电流){
cbRef.当前(状态)
cbRef.current=null
}
},[国家])
返回[状态,设置状态回调]
}
我应该在这里使用
any
,如果是,我如何正确使用
any
? 由于这是一个通用函数,可以在任何地方使用,如何正确键入它


我在我的示例中添加了一些尝试,正如您所看到的,我停止了,因为从我的角度来看,它只会以
any
类型结束。

首先,您需要让这个
useStateCallback
接受一个表示您的状态的通用参数。你会经常使用这个参数。我们称之为状态的
S

function useStateCallback<S>(initialState: S) { ... }
或者您可以键入reducer函数的参数,这些类型将被推断出来,这看起来更简洁,IMHO

const [state, setState] = useReducer(
  (state: S, newState: Partial<S>) => ({ ...state, ...newState }),
  initialState
)
对于
setStateCallback
,我们需要接受一个
Partial
与完整状态合并,以及一个只有完整状态作为参数的回调:

function setStateCallback(state: Partial<S>, cb: (state: S) => void) {
  cbRef.current = cb
  setState(state)
}
这是必需的,因为typescript默认将其视为数组,但您希望它是元组。您希望它不是一个包含两个类型为
[S,Callback]
的元素的元组,而是一个包含两个类型为
[S,Callback]
的元素的数组。将
作为const
追加到数组后,typescript会将数组视为常量,并将这些类型锁定到正确的位置

把所有这些放在一起,你会得到:

import React, { useReducer, useRef, useEffect, Reducer } from 'react'

function useStateCallback<S>(initialState: S) {
  const [state, setState] = useReducer<Reducer<S, Partial<S>>>(
    (state, newState) => ({ ...state, ...newState }),
    initialState
  )
  const cbRef = useRef<((state: S) => void) | null>(null)

  function setStateCallback(state: Partial<S>, cb: (state: S) => void) {
    cbRef.current = cb
    setState(state)
  }

  useEffect(() => {
    if (cbRef.current) {
      cbRef.current(state)
      cbRef.current = null
    }
  }, [state])

  return [state, setStateCallback] as const
}

// Type safe usage
function Component() {
  const [state, setStateCallback] = useStateCallback({ foo: 'bar' })

  console.log(state.foo)

  setStateCallback({ foo: 'baz' }, newState => {
    console.log(newState.foo)
  })

  return <div>{state.foo}</div>
}
import React,{useReducer,useRef,useffect,Reducer}来自“React”
函数useStateCallback(初始状态:S){
const[state,setState]=useReducer(
(state,newState)=>({…state,…newState}),
初始状态
)
const cbRef=useRef void)| null>(null)
函数setStateCallback(状态:部分,cb:(状态:S)=>void){
cbRef.current=cb
设置状态(状态)
}
useffect(()=>{
if(cbRef.电流){
cbRef.当前(状态)
cbRef.current=null
}
},[国家])
将[state,setStateCallback]作为常量返回
}
//类型安全使用
函数组件(){
const[state,setStateCallback]=useStateCallback({foo:'bar'})
console.log(state.foo)
setStateCallback({foo:'baz'},newState=>{
console.log(newState.foo)
})
返回{state.foo}
}

让我们看看你尝试了什么。@DennisVash我添加了我的尝试这个钩子的目的是什么?您将如何使用它,它与
useState
不同?你用回调做什么?(如果状态更改,React已经重新渲染,因此您通常不需要在状态更改时手动触发任何事件)@Alex Wayne我使用它来确保状态实际更改,并且我可以继续。这样我就可以在不使用react的外部函数中跟踪它,这样您就可以继续进行什么?因为这正是具有依赖项的效果所做的。只要
somethingFromState
完成保存更改,此
useffect(someFunction,[somethingFromState])
就会自动运行
someFunction
。谢谢,这对我帮助很大!Allthrough TS Playerd并不是要求键入函数的返回值,而是我的ESLint设置。如果我只是应用[S,Callback],它将不起作用,因为。。。什么是“回调”及其类型(从您上面的回答中)?
Callback
只是一个占位符,但它表示
type Callback=(state:s)=>void
。您不必键入函数的返回值,只要在末尾使用
作为const返回元组即可。
@Alex Wayne谢谢您的澄清
function setStateCallback(state: Partial<S>, cb: (state: S) => void) {
  cbRef.current = cb
  setState(state)
}
return [state, setStateCallback] as const
import React, { useReducer, useRef, useEffect, Reducer } from 'react'

function useStateCallback<S>(initialState: S) {
  const [state, setState] = useReducer<Reducer<S, Partial<S>>>(
    (state, newState) => ({ ...state, ...newState }),
    initialState
  )
  const cbRef = useRef<((state: S) => void) | null>(null)

  function setStateCallback(state: Partial<S>, cb: (state: S) => void) {
    cbRef.current = cb
    setState(state)
  }

  useEffect(() => {
    if (cbRef.current) {
      cbRef.current(state)
      cbRef.current = null
    }
  }, [state])

  return [state, setStateCallback] as const
}

// Type safe usage
function Component() {
  const [state, setStateCallback] = useStateCallback({ foo: 'bar' })

  console.log(state.foo)

  setStateCallback({ foo: 'baz' }, newState => {
    console.log(newState.foo)
  })

  return <div>{state.foo}</div>
}