I have no idea why this is not working
Demo
I have the following es6 code
const {createFactory, createClass, DOM: { label, input, button }} = React;
const tester = createFactory(createClass({
render() {
return label({}
,`Name: ${this.props.name}`
,input({defaultValue: this.props.name})
,button({onClick: this.changeName}, "Change")
)
},
changeName() {
this.setProps({name: "Wilma"})
}
}) )
React.render(tester({name: "Fred"}), document.querySelector('body'))
Clicking the button clearly changes the props, but the old defaultValue
is still in the input! So what gives? What am I doing wrong? is this a bug? Is there a workaround?
In order for props to change, they need to be updated by the parent component. This means the parent would have to re-render, which will trigger re-render of the child component regardless of its props.
A React component automatically re-renders whenever there is a change in state or props, it only takes a simple state update from anywhere in the code to automatically re-render UI elements. However, you may see cases where rendering depends on other data.
React components automatically re-render whenever there is a change in their state or props. A simple update of the state, from anywhere in the code, causes all the User Interface (UI) elements to be re-rendered automatically.
I found what seems to be a pretty good solution to this: Use the key
prop to force rendering of an entirely new input
.
In my particular case, I don't need the input
to be controlled with its own onChange
prop, as the form
surrounding it ultimately controls the state within some store which populates the defaultValue
. But the store's state might be asynchronously initialized/updated, and in which case the defaultValue
should be updated. So here is a condensed version of my particular case:
import React, { PropTypes } from 'react';
import { Form } from 'provide-page';
const GatherContact = ({
classes,
onSubmit,
movingContactName,
movingContactEmail,
movingContactPhone,
userName,
userEmail,
userPhone
}) => (
<Form onSubmit={onSubmit}>
<div className={classes.GatherContact}>
<h2 className={classes.GatherHeading}>
How can we contact you?
</h2>
<input
type="text"
className={classes.GatherContactInput}
placeholder="Name"
name="movingContactName"
key={`movingContactName:${movingContactName || userName}`}
defaultValue={movingContactName || userName}
required={true}
/>
<input
type="email"
className={classes.GatherContactInput}
placeholder="Email"
name="movingContactEmail"
key={`movingContactEmail:${movingContactEmail || userEmail}`}
defaultValue={movingContactEmail || userEmail}
required={true}
/>
<input
type="tel"
className={classes.GatherContactInput}
placeholder="Phone"
name="movingContactPhone"
key={`movingContactPhone:${movingContactPhone || userPhone}`}
defaultValue={movingContactPhone || userPhone}
required={true}
/>
{userName
? undefined
: (
<input
type="password"
className={classes.GatherContactInput}
placeholder="Password"
name="userPassword"
required={true}
autoComplete="new-password"
/>
)
}
</div>
</Form>
);
GatherContact.propTypes = {
classes: PropTypes.object.isRequired,
onSubmit: PropTypes.func.isRequired,
movingContactName: PropTypes.string.isRequired,
movingContactEmail: PropTypes.string.isRequired,
movingContactPhone: PropTypes.string.isRequired,
userName: PropTypes.string.isRequired,
userEmail: PropTypes.string.isRequired,
userPhone: PropTypes.string.isRequired
};
export default GatherContact;
You only specify its default value, but don't tell it to change its value with a change to props.
,input({value: this.props.name})
Will change the value when this.props.name changes.
http://output.jsbin.com/melitecimo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With