繁体   English   中英

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

[英]Inferring mapped props when using TypeScript and React-Redux

我找到了一种在使用mapStateToProps中的react-redux时获得类型安全的方法:如文档所述,您可以定义一个接口并使用您的接口参数化React.Component<T>

但是,当我定义mapStateToProps时,我已经定义了一个 function ,其中可以推断出结果 object 的属性类型。 例如,

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

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

interface AppProps {
    counter: number;
}


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

export default connect(mapStateToProps)(App);

所以问题是,有没有什么方法可以构造代码,这样我就可以避免两次编写counter的类型? 或者为了避免参数化React.Component的类型——即使我可以从mapStateToProps function 的明确提示的结果类型推断出组件的 props,这将是更可取的。 我想知道上面的重复是否确实是使用 React-Redux 编写类型化组件的正常方式。

是的。 有一种巧妙的技术可以根据mapStatemapDispatch推断connect的组合道具的类型。

@types/react-redux@7.1.2中有一个新的ConnectedProps<T>类型。 你可以像这样使用它:

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)

请注意,如果它是 object,则这会正确推断mapDispatch中包含的 thunk 动作创建者的类型,而typeof mapDispatch则不会。

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

更多细节:

我不这么认为。 您可以使用 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类型,则可以。 但我不认为你会想要那个。

我将分别键入映射的调度道具和组件道具,然后将映射的 state 的推断类型组合到道具 function。 请参阅下面的快速示例。 可能有一个更优雅的解决方案,但希望它能让你走上正确的轨道。

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;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM