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

Migration from react-redux to react-final-form

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

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

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

获取表格:

const form = useForm()

然后使用它的 .change 方法来更新我的 UI :

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, fetchEnd, 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,
  fetchEnd,
  showNotification,
  refreshView
})(AdminButton)

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

您不能在 Form 上下文之外使用 useFormuseFormState。也就是说,尝试将您的组件包装在 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 hook like

import {useForm} from 'react-final-form';

const AdminButton = () => {
  const form = useForm();
    
  const handleClick = async () => {
    ...
    form.change('isadmin', isAdmin);
    ...
  }
  ...
}

您正在 Class 组件内使用 React 挂钩。那是不允许的。尝试将您的组件转换为功能组件。