Skip to content

Commit

Permalink
Use componentDidMount instead of componentWillMount to register Field (
Browse files Browse the repository at this point in the history
…#3566) (#3956)

* Use componentDidMount instead of componentWillMount to register Field, Fields, FieldArray. Fixes #3566

* Test field validate prop after unregister and register Field #3566

* PR improvement, remove duplicate code.

* PR improvement. lint, remove semicolons

* Use constructor instead of componentWillMount to register Field, Fields, FieldArray. PR comment: #3956 (comment)

* Revert "Use constructor instead of componentWillMount to register Field, Fields, FieldArray. PR comment: #3956 (comment)"

This reverts commit 82781c0
  • Loading branch information
asaarnak authored and erikras committed Jun 15, 2018
1 parent a9e394c commit 647a21f
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 14 deletions.
82 changes: 82 additions & 0 deletions src/__tests__/Field.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2210,6 +2210,88 @@ const describeField = (name, structure, combineReducers, setup) => {
).toBe('Required')
})

it('should revalidate when Field unregisters and registers with new validate prop', () => {
const weightFieldName = 'weight'
const weightValue = 100
const initialWeightLimit = 20
const nextWeightLimit = 50
const store = makeStore({
testForm: {
values: {
weight: weightValue,
}
}
})
const renderWeight = jest.fn(props => <input {...props.input} />)
const weightValidationText = 'Max allowed weight is '
const getWeightLimitValidator = weightLimit => jest.fn(
value => (value > weightLimit ? weightValidationText + weightLimit : undefined)
)
class Form extends Component {

constructor() {
super()
this.state = {
weightLimit: initialWeightLimit,
validate: [ getWeightLimitValidator(initialWeightLimit) ]
}
}

render() {
// This will trigger unregister and register Field
// and these must happen in correct order for Field validation to work
const someCrazyBusinessLogic = this.state.weightLimit > 30
return (
<div>
{someCrazyBusinessLogic &&
<Field
name={weightFieldName}
component={renderWeight}
validate={this.state.validate}
/>
}
{!someCrazyBusinessLogic &&
<Field
name={weightFieldName}
component={renderWeight}
validate={this.state.validate}
/>
}
<button onClick={() => this.setState({
weightLimit: nextWeightLimit,
validate: [ getWeightLimitValidator(nextWeightLimit) ]
})}>
Change weight limit
</button>
</div>
)
}
}
const TestForm = reduxForm({form: testFormName})(Form)
const dom = TestUtils.renderIntoDocument(
<Provider store={store}>
<TestForm />
</Provider>
)

testWeightValidator(initialWeightLimit)
const changeWeightLimit = TestUtils.findRenderedDOMComponentWithTag(dom, 'button')
TestUtils.Simulate.click(changeWeightLimit)
testWeightValidator(nextWeightLimit)

function testWeightValidator(weightLimit) {
expect(
renderWeight.mock.calls[renderWeight.mock.calls.length - 1][0].meta
.valid
).toBe(false)
expect(
renderWeight.mock.calls[renderWeight.mock.calls.length - 1][0].meta
.error
).toBe(weightValidationText + weightLimit)
}

})

it('should sync warn with field level warning function', () => {
const store = makeStore()
const usernameInput = jest.fn(props => <input {...props.input} />)
Expand Down
10 changes: 5 additions & 5 deletions src/createField.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,7 @@ const createField = (structure: Structure<*, *>) => {
}
}

shouldComponentUpdate(nextProps: Props, nextState?: Object) {
return shallowCompare(this, nextProps, nextState)
}

UNSAFE_componentWillMount() {
componentDidMount() {
this.context._reduxForm.register(
this.name,
'Field',
Expand All @@ -47,6 +43,10 @@ const createField = (structure: Structure<*, *>) => {
)
}

shouldComponentUpdate(nextProps: Props, nextState?: Object) {
return shallowCompare(this, nextProps, nextState)
}

UNSAFE_componentWillReceiveProps(nextProps: Props, nextContext: any) {
const oldName = prefixName(this.context, this.props.name)
const newName = prefixName(nextContext, nextProps.name)
Expand Down
2 changes: 1 addition & 1 deletion src/createFieldArray.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ const createFieldArray = (structure: Structure<*, *>) => {
}
}

UNSAFE_componentWillMount() {
componentDidMount() {
this.context._reduxForm.register(
this.name,
'FieldArray',
Expand Down
14 changes: 6 additions & 8 deletions src/createFields.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,19 @@ const createFields = (structure: Structure<*, *>) => {
'Fields must be inside a component decorated with reduxForm()'
)
}
const error = validateNameProp(props.names)
if (error) {
throw error
}
}

shouldComponentUpdate(nextProps: Props) {
return shallowCompare(this, nextProps)
}

UNSAFE_componentWillMount() {
const error = validateNameProp(this.props.names)
if (error) {
throw error
}
componentDidMount() {
const { context } = this
const {
_reduxForm: { register }
} = context
const { _reduxForm: { register } } = context
this.names.forEach(name => register(name, 'Field'))
}

Expand Down

0 comments on commit 647a21f

Please sign in to comment.