通过mapStateToProps访问Redux形式的值

How can I access the field values in a parent component of a redux-form component?

I'm not sure if it's caused by typescript, but before I started using typescript, I was able to access the form values through mapStateToProps just like how I have it currently. I've been trying to figure out what was different to my previous implementation but the only difference would be the versions of the npm dependencies and the addition of typescript.

LoginPage.tsx

import LoginForm from 'components/Forms/LoginForm'
import Layout from 'components/Layout'
import { StatusCodes } from 'lib/enums/statusCodes'
import { storeAuthToken } from 'lib/helpers/auth'
import { NextPage } from 'next'
import Router from 'next/router'
import React from 'react'
import { connect, DispatchProp } from 'react-redux'
import { FormInstance } from 'redux-form'

interface IProps {
  login: FormInstance<IFormData, IFormProps>
}

interface IState {
  errorMessage?: string,
  processing: boolean
}

interface IRootState {
  form: IProps
}

export interface IFormData {
  username?: string,
  password?: string
}

export interface IFormProps {
  contactId?: string,
  errorMessage?: string,
  fieldValues: Partial<IFormData>,
  processing: boolean
}

class LoginPage extends React.Component<NextPage & DispatchProp & IProps, IState> {
  state = {
    errorMessage: undefined,
    processing: false
  }

  setErrorMessage = (message: string) => {
    this.setState({
      errorMessage: message,
      processing: false
    })
  }

  handleSubmit = async (values: IFormData) => {
    if (values && values.username && values.password) {
      this.setState({
        errorMessage: undefined,
        processing: true
      })
  
      try {
        const { dispatch } = this.props
  
        await storeAuthToken(dispatch, values.username, values.password)
        Router.push('/')
      } catch (error) {
        if (error === StatusCodes.BAD_REQUEST) {
          this.setErrorMessage("Sorry, you have entered incorrect details. Please try again.")
        } else {
          this.setErrorMessage("Sorry, there was an issue trying to log you in")
        }
      }
    }
  }

  render() {
    const { login } = this.props
    const { processing } = this.state

    return (
      <Layout title="Login">
        <div className="form-wrapper full">
          <LoginForm processing={processing} onSubmit={this.handleSubmit} fieldValues={login.values} />
        </div>
      </Layout>
    )
  }
}

const mapStateToProps = ({ form: { login } }: IRootState) => ({ login })

export default connect(mapStateToProps)(LoginPage)

LoginForm.tsx

import Link from 'next/link'
import React from 'react'
import { Field, InjectedFormProps, reduxForm } from 'redux-form'
import FormButton from 'components/Forms/FormButton'
import Input from 'components/Fields/Input'
import { validateRequired } from 'lib/helpers/validators'
import { IFormProps, IFormData } from 'pages/login'

class LoginForm extends React.Component<IFormProps & InjectedFormProps<IFormData, IFormProps>> {
  render() {
    const { contactId, errorMessage, fieldValues, handleSubmit, processing } = this.props

    return (
      <form id="login" onSubmit={handleSubmit} >
        <h1>Sign in</h1>
        <fieldset>
          <div className="fields">
            {
              !contactId
                ? <Field name="username" type="text" component={Input} label="Username" validate={validateRequired} />
                : <Field name="username" type="email" component={Input} label="Email" validate={validateRequired} />
            } 
          </div>
          <div className="fields">
            <Field name="password" type="password" component={Input} label="Password" validate={validateRequired} />
          </div>
        </fieldset>
        { errorMessage && <p className="error-message">{errorMessage}</p> }
        <div className="form-bottom">
          <Link href="/"/*{`/forgot-password${fields.email ? `?email=${encodeURIComponent(fields.email)}` : ''}`}*/>
            <a className="inline">Forgotten your password?</a>
          </Link>
          <FormButton loading={processing}>
            Login
          </FormButton>
        </div>
      </form>
    )
  }
}

export default reduxForm<{}, IFormProps>({ form: 'login' })(LoginForm)

这是我的redux存储文件,以防万一编码不正确

import { createWrapper, HYDRATE, MakeStore } from 'next-redux-wrapper'
import { AnyAction, applyMiddleware, combineReducers, createStore, Reducer } from 'redux'
import { reducer as formReducer } from 'redux-form'
import thunkMiddleware, { ThunkMiddleware } from 'redux-thunk'
import authReducer, { AuthState } from './auth/reducer'
import contactReducer, { ContactState } from './contact/reducer'
import initialState from './initialState'

export interface State {
  auth: AuthState
  contact: ContactState
}

const bindMiddleware = (middleware: [ThunkMiddleware]) => {
  if (process.env.NODE_ENV !== 'production') {
    const { composeWithDevTools } = require('redux-devtools-extension')
    return composeWithDevTools(applyMiddleware(...middleware))
  }

  return applyMiddleware(...middleware)
}

const combinedReducer = combineReducers({
  auth: authReducer,
  contact: contactReducer,
  form: formReducer
})

const reducer: Reducer = (state: State, action: AnyAction) => {
  if (action.type === HYDRATE) {
    const nextState: Reducer = {
      ...state,
      ...action.payload
    }

    return nextState
  } else {
    return combinedReducer
  }
}

const makeStore: MakeStore<State> = () => createStore(reducer, initialState, bindMiddleware([thunkMiddleware]))

export const wrapper = createWrapper<State>(makeStore/*, { debug: true }*/)