Reputation: 1
I have a large (3+ year old) React Redux project which uses a lot of Redux-Form. As that is now discontinued I am doing new features in react-final-form. It has been pretty easy to move to final-form but I was using some advanced features of redux-form that have no equivalent in final-form. I need a component that is outside of the form to know when the form is dirty, submitting etc.
Final-form suggests FormSpy for this, which works, but I have come up against React's Warning:
Cannot update during an existing state transition (such as within render)
So, really, this is as much a React as a Final-Form question. I have put an example app below illustrating the problem. In summary a parent Component <Parent/>
renders a bunch of child components. One of those is a final-form instance <TheForm/>
, one of the other child components, <ShowFormState/>
, renders the form's state (eg whether the form is dirty). Importantly ShowFormState
is a sibling of the form, not within it. In Redux-Form this was simple: ShowFormState
could just grab the form's state from redux but final-form has no equivalent so the Parent
uses FormSpy's onChange()
and stores the state in it's own state and passes that to its child ShowFormState
as props.
React no likey and I get the above error (which after 3 years of working in React I have not seen before!). The warning is totally understandable, that is not the question. I am just a bit stuck on how to work around it, with the given structure.
The sample App is below, I hope it is clear enough :). Anyone who has migrated from redux-form to final-form bumped into a similar problem?
import React , {Component} from 'react'
import {Form, FormSpy, Field } from 'react-final-form'
class Parent extends Component {
constructor(props){
super(props)
this.state = {}
}
onSubmit = () => { console.log("Submitted!") }
onChange = ({dirty}) => {
// triggers rerender DURING render so cant do this
this.setState({ dirty })
}
render = () => (
<>
<TheForm
onChange={this.onChange}
onSubmit={this.onSubmit}
/>
{/*other components ...*/}
<ShowFormState dirty={this.state.dirty}/>
</>
)
}
const ShowFormState = ({dirty}) => dirty ? <p>dirty!</p> : null
const TheForm = ({onChange, onSubmit}) => (
<Form
onSubmit={onSubmit}
initialValues={{ name:'' }}>
{({ handleSubmit }) => (
<form className="wrap" onSubmit={handleSubmit}>
<label>
Name:
<Field name="name" component="input"/>
</label>
{<FormSpy onChange={onChange}/>}
</form>
)}
</Form>
)
function App() {
return <Parent />
}
export default App;
Thanks in advance for any help :)
Upvotes: 0
Views: 3941