【问题标题】:use redux with typeScript使用带有 typeScript 的 redux
【发布时间】:2021-03-05 03:12:41
【问题描述】:

我是新手,最近才使用 Redux。

这是我的代码:

import React from "react";
import { View, Text, TouchableOpacity } from "react-native";
import { connect } from "react-redux";
import { useNavigation } from "@react-navigation/native";
import { controlComponent1 } from "../redux/reduce";

import style from "./style";

const Component1 = (props) => {
  const navigation = useNavigation();
  return (
    <View
      style={[
        props.style,
        style.container,
        props.show1 ? { backgroundColor: "green" } : null
      ]}
    >
      <Text>show cai nay :v ...</Text>
      <TouchableOpacity style={style.button} onPress={() => props.chance1}>
        <Text>color</Text>
      </TouchableOpacity>
      <TouchableOpacity
        style={style.button}
        onPress={() => navigation.navigate("component2")}
      >
        <Text> next</Text>
      </TouchableOpacity>
    </View>
  );
};

function mapStateToProps(state) {
  return {
    show1: state.show1
  };
}

function mapDispatchToProps(dispatch) {
  return {
    chance1: dispatch(controlComponent1)
  };
}

export default connect(mapStateToProps, mapDispatchToProps)(Component1);

我知道mapDispatchToProps()mapStateToProps() 两个函数将使chance1show1 两个值成为我组件的道具,但我不知道如何在我的组件中使用它,因为我使用的是TypeScript .

我在这些图片上收到警告:

谁能帮我解决这个问题?

【问题讨论】:

  • 您必须将props 的类型声明为包含预期道具和connect 添加的道具。在我看来,使用 useSelectoruseDispatch 挂钩更容易。
  • 你能举个例子吗,我以前只使用接口,像这样:** interface Props{ style: object, show1: boolean, chance1:()=>void, } ** and添加到组件中,例如:** const Component1 = (props: Props) =>{} ** 我之前从未使用过 useSelector 和 useDispatch

标签: typescript react-redux


【解决方案1】:

如果你分两步分离你的连接,你可以获得你的道具类型,以便有一个备用的 const 来推断类型:

import { connect, ConnectedProps } from 'react-redux';

const connector = connect(mapStateToProps, mapDispatchToProps)
type Props = ConnectedProps<typeof connector> //your props type

export default connector(Component1)

然后使用你的组件:

const Component1 = (props:Props) => {}

【讨论】:

  • 谢谢你的回答,我学会了钩子,用useDispatch和useSelector解决了我的问题,真的很简单,你认为我应该用Hook来代替mapStateToProps,mapDispatchToProps吗?
  • 根据我对 react 的理解,这并不多,我会使用简短的钩子或不使用大型应用程序来处理沿着组件层次结构向下流动的封装状态。如果这种情况失控并且您需要沿着组件的“水平”层次结构(而不​​是从父级到子级)与您的组件进行通信,您可以尝试unstated。如果这种“水平通信”一直在发生并且在非常“远离层次结构”的组件之间发生并且你的应用程序变得很大,那么我你会使用 react.redux。
  • 另一个使用 redux 的情况是组件的层次结构非常大,因此即使组件通信可能不是水平的,您可能需要将 prop 传递给层次结构中非常深的子级通过许多不需要该道具的组件,只需通过它即可。这就是所谓的支柱“钻孔”。在这种情况下,您还可以检查钩子替代品:)
【解决方案2】:

您的组件需要知道它正在接收什么道具才能访问它们。所以我们需要为组件的 props 声明一个类型,其中包括 Redux connect 添加的 props 以及调用时传递给组件的 props。

您可以将类型直接分配给props,例如= (props: Component1Props) =&gt;,或者将React.FunctionComponent&lt;Props&gt; / React.FC&lt;Props&gt; 类型分配给具有正确道具的组件,例如const Component1: FunctionComponent&lt;Component1Props&gt; = (props) =&gt;

在组件中使用useSelectoruseDispatchconnect 更容易获得打字稿支持。还有this is the recommended approach

带挂钩

import React, { FunctionComponent } from "react";
import { View, Text, TouchableOpacity, ViewStyle } from "react-native";
import { useDispatch, useSelector } from "react-redux";
import { useNavigation } from "@react-navigation/native";
import { controlComponent1 } from "../redux/reduce";
import style from "./style";
import { RootState } from "./path/store";
// ^ some type for your app's specific state type

interface Component1Props {
  // own props
  style?: ViewStyle;
}

const Component1: FunctionComponent<Component1Props> = (props) => {
  const navigation = useNavigation();

  // type will be automatically inferred if `RootState` is correct
  const show1 = useSelector((state: RootState) => state.show1);

  // we don't map dispatch the same way with hooks
  // we get access to the dispatch function and then call it
  const dispatch = useDispatch();

  return (
    <View
      style={[
        props.style,
        style.container,
        show1 ? { backgroundColor: "green" } : null
      ]}
    >
      <Text>show cai nay :v ...</Text>
      <TouchableOpacity
        style={style.button}
        // call dispatch with the action from your action creator
        onPress={() => dispatch(controlComponent1())}
      >
        <Text>color</Text>
      </TouchableOpacity>
      <TouchableOpacity
        style={style.button}
        onPress={() => navigation.navigate("component2")}
      >
        <Text> next</Text>
      </TouchableOpacity>
    </View>
  );
};

export default Component1;

使用连接

import React, {FunctionComponent} from "react";
import { View, Text, TouchableOpacity, ViewStyle } from "react-native";
import { connect } from "react-redux";
import {Dispatch} from "redux";
import { useNavigation } from "@react-navigation/native";
import { controlComponent1 } from "../redux/reduce";
import style from "./style";
import {RootState} from "./path/store";
// ^ some type for your app's specific state type

interface Component1Props {
  // own props
  style?: ViewStyle;
  // from mapStateToProps
  show1: boolean;
  // from mapDispatchToProps
  chance1: () => void;
}

const Component1: FunctionComponent<Component1Props> = (props) => {
  const navigation = useNavigation();
  return (
    <View
      style={[
        props.style,
        style.container,
        props.show1 ? { backgroundColor: "green" } : null
      ]}
    >
      <Text>show cai nay :v ...</Text>
      <TouchableOpacity style={style.button} onPress={() => props.chance1}>
        <Text>color</Text>
      </TouchableOpacity>
      <TouchableOpacity
        style={style.button}
        onPress={() => navigation.navigate("component2")}
      >
        <Text> next</Text>
      </TouchableOpacity>
    </View>
  );
};

function mapStateToProps(state: RootState) {
  return {
    show1: state.show1
  };
}

function mapDispatchToProps(dispatch: Dispatch) {
  return {
    // if this is an action creator then you need to call it!
    chance1: dispatch(controlComponent1())
  };
}

export default connect(mapStateToProps, mapDispatchToProps)(Component1);

【讨论】:

  • 我已经使用 Hooks 来解决我的问题,它更容易。我尝试使用 connect 作为您的建议,但它有一个错误:'FunctionComponent' 类型的参数不可分配给'ComponentType>'.
猜你喜欢
  • 2019-11-14
  • 2021-11-22
  • 1970-01-01
  • 2021-11-24
  • 2020-10-09
  • 2019-09-30
  • 1970-01-01
  • 2022-01-22
  • 2021-06-03
相关资源
最近更新 更多