使用TypeScript和React-Redux时推断映射的道具

时间:2019-10-30 10:30:41

标签: javascript reactjs typescript redux react-redux

我找到了一种使用mapStateToProps中的react-redux时获得类型安全性的方法:作为the documentation,您可以定义一个接口并使用该接口参数化React.Component<T>

但是,当我定义mapStateToProps时,我已经在定义一个函数,可以在该函数中推断结果对象的属性类型。例如,

function mapStateToProps(state: MyState) {
    return {
        counter: state.counter
    };
}

在这里,可以推断道具counterstate.counter的类型相同。但是我仍然必须具有如下的样板代码:

interface AppProps {
    counter: number;
}


class App extends React.Component<AppProps> { ... }

export default connect(mapStateToProps)(App);

所以问题是,有什么方法可以构造代码,以便避免两次编写counter类型的代码?或者,为了避免参数化React.Component的类型,即使我可以从mapStateToProps函数的显式结果类型中推断出组件的属性,那还是更好的选择。我想知道上面的复制是否确实是使用React-Redux编写类型化组件的正常方法。

3 个答案:

答案 0 :(得分:3)

我不这么认为。您可以使用Redux钩子来简化设置:https://react-redux.js.org/next/api/hooks

    // Your function component . You don't need to connect it
    const App: React.FC = () => {
      const counter = useSelector<number>((state: MyState) => state.counter);
      const dispatch = useDispatch(); // for dispatching actions
    };

编辑:如果您只使用相同的MyState类型,则可以。但是我不认为你会那样想要。

答案 1 :(得分:3)

是的。有一种精巧的技术可以根据 shell: /bin/bash -e {0} npm WARN Gatsby_site No repository field. npm WARN Gatsby_site No license field. added 33 packages from 26 contributors and audited 43 packages in 0.952s found 0 vulnerabilities > @ test /home/runner/work/Gatsby_site/Gatsby_site > bash mdlint.sh fatal: ambiguous argument 'master': unknown revision or path not in the working tree. Use '--' to separate paths from revisions, like this: 'git <command> [<revision>...] -- [<file>...]' connect来推断mapState将传递给组件的组合道具的类型。

mapDispatch中有一个新的ConnectedProps<T>类型。您可以像这样使用它:

@types/react-redux@7.1.2

请注意,如果function mapStateToProps(state: MyState) { return { counter: state.counter }; } const mapDispatch = {increment}; // Do the first half of the `connect()` call separately, // before declaring the component const connector = connect(mapState, mapDispatch); // Extract "the type of the props passed down by connect" type PropsFromRedux = ConnectedProps<typeof connector> // should be: {counter: number, increment: () => {type: "INCREMENT"}}, etc // define combined props type MyComponentProps = PropsFromRedux & PropsFromParent; // Declare the component with the right props type class MyComponent extends React.Component<MyComponentProps> {} // Finish the connect call export default connector(MyComponent) 是对象,则可以正确推断出mapDispatch中包含的重击动作创建者的类型,而typeof mapDispatch则不是。

作为推荐的方法,我们很快会将其添加到React-Redux官方文档中。

更多详细信息:

答案 2 :(得分:2)

我将分别键入映射的调度道具和组件道具,然后将映射状态的推断类型组合到道具功能。请参见下面的快速示例。也许会有更优雅的解决方案,但希望它能使您走上正确的轨道。

import * as React from "react";
import { Action } from "redux";
import { connect } from "react-redux";

// Lives in some lib file
type AppState = {
  counter: number;
};

type MappedState = {
  computedValue: number;
};
type MappedDispatch = {
  doSomethingCool: () => Action;
};
type ComponentProps = {
  someProp: string;
};

const mapStateToProps = (state: AppState) => ({
  computedValue: state.counter
});

const mapDispatchToProps: MappedDispatch = {
  doSomethingCool: () => {
    return {
      type: "DO_SOMETHING_COOL"
    };
  }
};

type Props = ReturnType<typeof mapStateToProps> &
  MappedDispatch &
  ComponentProps;

class DumbComponent extends React.Component<Props> {
  render() {
    return (
      <div>
        <h1>{this.props.someProp}</h1>
        <div>{this.props.computedValue}</div>
        <button onClick={() => this.props.doSomethingCool()}>Click me</button>
      </div>
    );
  }
}

const SmartComponent = connect(
  mapStateToProps,
  mapDispatchToProps
)(DumbComponent);

export default SmartComponent;