如何创建使用 Typescript 传递函数的 React Context

Posted

技术标签:

【中文标题】如何创建使用 Typescript 传递函数的 React Context【英文标题】:How to create React Context that passes a function with Typescript 【发布时间】:2021-09-26 19:01:07 【问题描述】:

我正在尝试使用 React Context 传递状态的 setter 函数。但是,我收到一个 Typescript 错误“类型‘null’不可分配给类型‘(值:数字)=> void’。”当我尝试为其分配默认值时。

我该如何解决?非常感谢

context.tsx

import React from "react";
import  Movie  from "./movies.service";

export const MoviesContext = React.createContext<
    movies: Movie[];
    selectedMovie: number;
    setSelectedMovie: (value: number) => void;
  >(
    movies: [],
    selectedMovie: 0,
    setSelectedMovie: null, // ERROR IS SHOWN HERE
  );

App.tsx

import React,  useState, useEffect  from "react";
import './App.css';
import HomePage from './components/Pages/HomePage';
import  Movie, fetchMovies  from "./services/movies.service";
import  MoviesContext  from "./services/context";
import MoviePage from './components/Pages/MoviePage';

const Router = require("react-router-dom").BrowserRouter;
const Route = require("react-router-dom").Route;
const Switch = require("react-router-dom").Switch;

function App() 
  useEffect(() => 
    fetchMovies()
      .then(setMovies)
      .catch(() => setMovies([]));
  , []);

  const [movies, setMovies] = useState<Movie[]>([]);
  const [selectedMovie, setSelectedMovie] = useState(0);

  return (
    <MoviesContext.Provider value= movies, selectedMovie, setSelectedMovie >
      <div className="App">
        <div className="container typography-base">
          <Router>
            <Switch>
              <Route path="/movie/:movieid" >
              <MoviePage />
              </Route>
            </Switch>
          </Router>
        </div>
      </div>
    </MoviesContext.Provider>
  );

export default App;

【问题讨论】:

【参考方案1】:

您的类型期望setSelectedMovie 是一个函数,但您将默认值设置为null。尝试提供一个默认的函数实现。

export const MoviesContext = React.createContext<
    movies: Movie[];
    selectedMovie: number;
    setSelectedMovie: (value: number) => void;
  >(
    movies: [],
    selectedMovie: 0,
    setSelectedMovie: () => ,
  );

【讨论】:

难道它还不需要value:number 参数吗? @ksav 是的,打字稿将强制传入一个数字。尽管函数实际上 use 并不要求该数字,所以() =&gt; 是一个非常好的实现(value: number) =&gt; void. 非常感谢马特和尼古拉斯。你能解释一下为什么() =&gt; 有效吗? () =&gt; 是一个不返回任何内容的函数(隐式返回 undefined)。 (value: number) =&gt; void 类型意味着它是一个将数字作为参数并且不返回任何内容的函数。如果使用它们,您的实际函数实现必须与参数类型匹配,但您不需要使用参数。这与您将函数定义为 (value) =&gt; 基本相同,但您没有使用 value 参数。

以上是关于如何创建使用 Typescript 传递函数的 React Context的主要内容,如果未能解决你的问题,请参考以下文章

TypeScript:如何在 0.8.0.0 之后的版本中将 null 传递给重载函数?

R语言编程时如何传递文件名参数

TypeScript:如何在0.8.0.0之后的版本中将null传递给重载函数?

如何将参数从 Dart 传递到用 Typescript 编写的 Cloud 函数,它还给了我错误代码 UNAUTHENTICATED

TypeScript 中的函数重载与使用联合类型

通过 React 高阶组件传递子道具的正确 TypeScript 类型