Typescript react redux - 连接

时间:2017-10-08 07:59:58

标签: typescript react-redux

来自JavascriptServices网站的此模式和以下模式的新手,其中使用了带有React / Redux的Typescript。

我的是React Redux项目。

我有一个菜单tsx文件,显示一个菜单,该菜单与JavascriptServices中名为“NavMenu.tsx”的样板产品基本上没有改变

我想使用几个状态变量“IsAuthorised”& “用户名”。它们处于redux状态,我想只使用它们而不是设置它们等。

我在底部的connect语句中收到以下错误,特别是(NavMenu)是红色的,并且不知道如何修复此错误?

  

[TS]   “typeof NavMenu”类型的参数不能分配给“Component&”类型的参数。 LoginState>”。     类型'typeof NavMenu'不能分配给'StatelessComponent& LoginState>”。       类型'typeof NavMenu'不提供签名'(props:DispatchProp& LoginState& {children?:ReactNode;},context?:any):ReactElement'。

以下是NavMenu类的代码 - 错误位于最后一行:

  import * as React from "react";
  import { NavLink, Link } from "react-router-dom";
  import {
    Navbar,
    Nav,
    NavItem,
    NavDropdown,
    MenuItem,
    Glyphicon
  } from "react-bootstrap";
  import { LinkContainer } from "react-router-bootstrap";
  import { connect } from "react-redux";
  import { ApplicationState } from "../store";
  import * as LoginState from "../store/Login";

  // At runtime, Redux will merge together...
  type NavMenuProps = LoginState.LoginState;

  export class NavMenu extends React.Component<NavMenuProps, {}> {
    public render() {
      return (
        <div className="main-nav">
          <div className="navbar navbar-inverse">
            <div className="navbar-header">
              <button
                type="button"
                className="navbar-toggle"
                data-toggle="collapse"
                data-target=".navbar-collapse"
              >
                <span className="sr-only">Toggle navigation</span>
                <span className="icon-bar" />
                <span className="icon-bar" />
                <span className="icon-bar" />
              </button>
              <Link className="navbar-brand" to={"/"}>
                JobsLedger_API
              </Link>
            </div>
            <div className="clearfix" />
            <div className="navbar-collapse collapse">
              <ul className="nav navbar-nav">
                <li>
                  <NavLink exact to={"/"} activeClassName="active">
                    <span className="glyphicon glyphicon-home" /> Home
                  </NavLink>
                </li>
                <li>
                  <NavLink to={"/counter"} activeClassName="active">
                    <span className="glyphicon glyphicon-education" /> Counter
                  </NavLink>
                </li>
                <li>
                  <NavLink to={"/fetchdata"} activeClassName="active">
                    <span className="glyphicon glyphicon-th-list" /> Fetch data
                  </NavLink>
                </li>
              </ul>
            </div>
          </div>
        </div>
      );
    }
  }

  export default connect(
    (state: ApplicationState) => state.login // Selects which state properties are merged into the component's props
  )(NavMenu) as typeof NavMenu;

enter image description here

修改

我注意到第一条评论,但需要有人对其进行扩展。

我在JavascriptServices示例中关注的文件如下所示。我已经遵循了他们的连接语法..在那个例子中没有提到mapStateToProps ......

这是:

            import * as React from 'react';
        import { Link, RouteComponentProps } from 'react-router-dom';
        import { connect } from 'react-redux';
        import { ApplicationState }  from '../store';
        import * as WeatherForecastsState from '../store/WeatherForecasts';

        // At runtime, Redux will merge together...
        type WeatherForecastProps =
            WeatherForecastsState.WeatherForecastsState        // ... state we've requested from the Redux store
            & typeof WeatherForecastsState.actionCreators      // ... plus action creators we've requested
            & RouteComponentProps<{ startDateIndex: string }>; // ... plus incoming routing parameters

        class FetchData extends React.Component<WeatherForecastProps, {}> {
            componentWillMount() {
                // This method runs when the component is first added to the page
                let startDateIndex = parseInt(this.props.match.params.startDateIndex) || 0;
                this.props.requestWeatherForecasts(startDateIndex);
            }

            componentWillReceiveProps(nextProps: WeatherForecastProps) {
                // This method runs when incoming props (e.g., route params) change
                let startDateIndex = parseInt(nextProps.match.params.startDateIndex) || 0;
                this.props.requestWeatherForecasts(startDateIndex);
            }

            public render() {
                return <div>
                    <h1>Weather forecast</h1>
                    <p>This component demonstrates fetching data from the server and working with URL parameters.</p>
                    { this.renderForecastsTable() }
                    { this.renderPagination() }
                </div>;
            }

            private renderForecastsTable() {
                return <table className='table'>
                    <thead>
                        <tr>
                            <th>Date</th>
                            <th>Temp. (C)</th>
                            <th>Temp. (F)</th>
                            <th>Summary</th>
                        </tr>
                    </thead>
                    <tbody>
                    {this.props.forecasts.map(forecast =>
                        <tr key={ forecast.dateFormatted }>
                            <td>{ forecast.dateFormatted }</td>
                            <td>{ forecast.temperatureC }</td>
                            <td>{ forecast.temperatureF }</td>
                            <td>{ forecast.summary }</td>
                        </tr>
                    )}
                    </tbody>
                </table>;
            }

            private renderPagination() {
                let prevStartDateIndex = (this.props.startDateIndex || 0) - 5;
                let nextStartDateIndex = (this.props.startDateIndex || 0) + 5;

                return <p className='clearfix text-center'>
                    <Link className='btn btn-default pull-left' to={ `/fetchdata/${ prevStartDateIndex }` }>Previous</Link>
                    <Link className='btn btn-default pull-right' to={ `/fetchdata/${ nextStartDateIndex }` }>Next</Link>
                    { this.props.isLoading ? <span>Loading...</span> : [] }
                </p>;
            }
        }

        export default connect(
            (state: ApplicationState) => state.weatherForecasts, // Selects which state properties are merged into the component's props
            WeatherForecastsState.actionCreators                 // Selects which action creators are merged into the component's props
        )(FetchData) as typeof FetchData;

1 个答案:

答案 0 :(得分:2)

假人是对的。根据Redux文档:

  

[mapStateToProps(state,[ownProps]):stateProps](Function):如果指定了此参数,则新组件将订阅Redux存储更新。这意味着每次更新商店时,都会调用mapStateToProps。 mapStateToProps的结果必须是普通对象,它将合并到组件的props中。如果您不想订阅商店更新,请传递null或undefined代替mapStateToProps。

mapStateToProps内,您要将Redux商店的部分映射到您需要定义的本地prop 。大多数mapStateToProps来电都是这样的:

const mapStateToProps = (state) => {
    return {
        login: state.login
    };
};

现在prop login已映射到Redux商店中的login值。我对上述代码同样感到困惑,因为state.weatherForecasts未分配给任何prop,因此无法访问。我看到他们使用名为forecasts的道具但是从interface定义是否无法判断prop是从父母传来还是应该属于他们的store 。我会坚持使用mapStateToProps以上述方式 - 它在社区中非常标准,并且与TS一致。