从 react-redux 到 react-final-form 的迁移

问题描述

我将我的 react-admin 项目更新到 v3,此版本更新中的一些更改包括react-redux 迁移到 react-final-form,我正在尝试修复与此相关的一些错误改变。

我可能没有正确使用 react-final-form - 我曾经使用 .change() 函数将更改后的输入字段值连接到商店。

我遵循了 react-final-form 文档,并尝试像这样更改它:

获取表格:

const form = useForm()

然后使用它的 .change 方法更新我的用户界面:

form.change('isadmin',this.state.isAdmin)

但我收到此错误

Uncaught (in promise) Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This Could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.

这是我的 AdminButton 组件的样子:

import React,{ Component } from 'react'
import { connect } from 'react-redux'
import Switch from '@material-ui/core/Switch'
import { showNotification,fetchStart,fetchEnd,refreshView } from 'react-admin'
import { httpClient } from '../../dataProvider'
import { getFormValues } from 'redux-form'
import { useForm } from 'react-final-form'

const AdminButtonStyle = {
  zIndex: 2,display: 'inline-block',float: 'right',color: 'black'
}

class AdminButton extends Component {
  state = {
    isAdmin: this.props.formStates && this.props.formStates.isadmin
  }

  handleClick = async () => {
    const form = useForm()
    const { fetchStart,record,showNotification } = this.props
    this.setState({
      isAdmin: !this.state.isAdmin
    })
    fetchStart()
    try {
      await httpClient(
        `api/users/${record.id}`,{ method: 'PATCH',body: JSON.stringify({ isadmin: !this.state.isAdmin }) })
      form.change('isadmin',this.state.isAdmin)
      showNotification(`toggled user admin: ${this.state.isAdmin}`,'success',{ autoHideDuration: 10000 })
    } catch (err) {
      showNotification(`Error: ${err.data || err.message}`,'warning',{ autoHideDuration: 10000 })
    } finally {
      fetchEnd()
    }
  }

  render () {
    return <div style={AdminButtonStyle}>
      <span>Make Admin</span>
      <Switch
        checked={this.state.isAdmin}
        variant='raised'
        color='primary'
        size='large'
        onClick={this.handleClick}>
      </Switch>
    </div>
  }
}

function mapStatetoProps (state) {
  return {
    formStates: getFormValues('record-form')(state)
  }
}

export default connect(mapStatetoProps,{
  fetchStart,showNotification,refreshView
})(AdminButton)

那么谁能帮我理解我做错了什么?非常感谢!

解决方法

您不能在 import React from "react"; import { connect } from "react-redux"; import * as courseActions from "../../redux/actions/courseActions"; import PropTypes from "prop-types"; import { bindActionCreators } from "redux"; import history from './history' class CoursesPage extends React.Component { state = { course: { title: "",},}; handleSubmit = (event) => { event.preventDefault(); this.props.actions.loadCourses.createCourse(this.state.course).then(() => { alert('Inside Promise') history.push('/AllCourses'); //This doesn't get executed. }; render() { return ( <div> <form onSubmit={this.handleSubmit}> <h2>Courses</h2> <h3>Add Course</h3> <input type="submit" value="Add Course" /> {this.props.courses.map((course) => ( <div key={course.title}>{course.title}</div> ))} </form> <hr /> </div> ); } } CoursesPage.propTypes = { courses: PropTypes.array.isRequired,actions: PropTypes.object.isRequired,}; function mapStateToProps(state) { return { courses: state.courses,}; } function mapDispatchToProps(dispatch) { return { actions: { loadCourses: bindActionCreators(courseActions,dispatch),}; } export default connect(mapStateToProps,mapDispatchToProps)(CoursesPage); Action Code: import * as types from "./actionTypes"; export function createCourse(course) { return { type: types.CREATE_COURSE,course }; } Reducer: import * as types from "../actions/actionTypes"; export default function courseReducer(state = [],action) { debugger; switch (action.type) { case types.CREATE_COURSE: return [...state,{ ...action.course }]; default: return state; } } history.js import createHistory from 'history/createHashHistory' export default createHistory() 上下文之外使用 useFormuseFormState。也就是说,尝试将您的组件包装在 Form 之类的

Form

或直接使用 import { SimpleForm } from 'react-admin'; <SimpleForm {...props}> ... // your component </SimpleForm> 组件

react-final-form

然后在你的组件中,你可以使用 import { Form } from 'react-final-form'; <Form onSubmit={handleSubmit}> {({ handleSubmit }) => ( <form onSubmit={handleSubmit}> ... // You component </form> )} </Form> 钩子

useForm