Reputation: 553
I updated my react-admin
project to v3, some of the changes in this version update included migration from from react-redux
to react-final-form
and i'm trying to fix some bugs related to this change.
I'm probably not using react-final-form
right- I used to use the .change()
function which connected my changed input field values to the store.
I followed react-final-form
docs, and tried changing it like this:
get the form:
const form = useForm()
then use it's .change
method to update my UI :
form.change('isadmin', this.state.isAdmin)
but im getting this error:
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.
here's is how my AdminButton component looks like:
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)
So can anyone help me understand what i'm doing wrong? Many thanks!
Upvotes: 0
Views: 1043
Reputation: 81
You are using a React hook inside of a Class component. That's not allowed. Try to convert your component to a functional component.
Upvotes: 0
Reputation: 2547
You can't use the useForm
or useFormState
outside a Form
context. That said, try to wrap your component inside a Form
like
import { SimpleForm } from 'react-admin';
<SimpleForm {...props}>
... // your component
</SimpleForm>
or use the react-final-form
component directly
import { Form } from 'react-final-form';
<Form onSubmit={handleSubmit}>
{({ handleSubmit }) => (
<form onSubmit={handleSubmit}>
... // You component
</form>
)}
</Form>
Then in you component, you can use useForm
hook like
import {useForm} from 'react-final-form';
const AdminButton = () => {
const form = useForm();
const handleClick = async () => {
...
form.change('isadmin', isAdmin);
...
}
...
}
Upvotes: 2