Reputation: 95
I have some Card
(more than 10 Card component
) in a Cards component
and each Card has a form with more than 10 textField components
. When I'm typing in textFields, It has delay between type and update value of textField. After spending more than 2 days, I found my problem. I think it's related to re-rendering all Childs (all Card components) when I set my value in statein value update... .
I want to know where am I wrong? If my codes is standard, is there any way to stop re-rendering all Childs after changing state for just one textField?
My codes are like as follow:
MainComponent:
export default class MainComponent extends Component {
constructor(props) {
super(props);
this.state = {
value : {}
};
}
static PropTypes = {
results: PropTypes.array.isRequired
};
handleChange(ref, e) {
this.state.value[ref] = e;
this.setState(this.state);
}
render() {
const { results } = this.props;
<Cards>
{
results.map((result, index) => {
var ref_taxtfield1 = result.id + "taxtfield1";
var ref_taxtfield2 = result.id + "taxtfield2";
var ref_taxtfield3 = result.id + "taxtfield3";
var ref_taxtfield4 = result.id + "taxtfield4";
var ref_taxtfield5 = result.id + "taxtfield5";
return <Card key={ result.id } style={ styles.card }>
<Form>
<div style={ styles.innerContainer }>
<Textfield
name="taxtfield1"
label="My Label 1"
ref={ref_taxtfield1}
onValueChange={this.handleChange.bind(this, ref_taxtfield1)}
value={this.state.value[ref_taxtfield1]}
/>
<Textfield
name="taxtfield2"
label="My Label 2"
ref={ref_taxtfield2}
onValueChange={this.handleChange.bind(this, ref_taxtfield2)}
value={this.state.value[ref_taxtfield2]}
/>
<Textfield
name="taxtfield3"
label="My Label 3"
ref={ref_taxtfield3}
onValueChange={this.handleChange.bind(this, ref_taxtfield3)}
value={this.state.value[ref_taxtfield3]}
/>
<Textfield
name="taxtfield4"
label="My Label 4"
ref={ref_taxtfield4}
onValueChange={this.handleChange.bind(this, ref_taxtfield4)}
value={this.state.value[ref_taxtfield4]}
/>
<Textfield
name="taxtfield5"
label="My Label 5"
ref={ref_taxtfield5}
onValueChange={this.handleChange.bind(this, ref_taxtfield5)}
value={this.state.value[ref_taxtfield5]}
/>
</div>
</Form>
</Card>})}
</Cards>
}
}
My TextField Component
export default class Textfield extends Input {
static defaultProps = {
initialCount: 0,
value: "",
defaultValue: "",
onValueChange: null,
label: ""
};
state = { focused: false };
onChange = this.onChange.bind(this);
onChange(e) {
if(this.props.onValueChange){
this.props.onValueChange(e.target.value);
}
}
handleOnBlur = this.handleOnBlur.bind(this);
handleOnBlur(e){
this.setState({focused: false});
if(this.props.onBlur){
this.props.onBlur(e);
}
}
render() {
const { focused } = this.state;
const { value, disabled } = this.props;
return (
<div>
<label>{this.props.label}</label>
<input
{ ...this.inputProps() }
type="text"
placeholder={this.props.placeholder}
defaultValue={this.props.defaultValue}
onChange={this.onChange}
onBlur={this.handleOnBlur}
value={ isCurrency ? formatData.currency(value) : value}
disabled={disabled}
/>
</div>
)
}
}
My Card and Cards Component
export class Cards extends Component {
render() {
const { children, ...props } = this.props;
return <div {...props} >{ children }</div>;
}
};
export class Card extends Component {
render() {
const { ...props } = this.props;
return <div {...props} } />
}
}
I use ES6 syntax and also remove all style tags from my code to simplify.
Upvotes: 1
Views: 523
Reputation: 816424
You are passing a new function to every Textfield
component on render:
onValueChange={this.handleChange.bind(this, ref_taxtfield1)}
.bind
returns a new function every time, causing every Textfield
to render on each update.
Two possible solutions:
.bind
inside .render
. .bind
the method once in the constructor and let Textfield
pass an identifier to this.props.onValueChange
.shouldComponentUpdate
in Textfield
, returning false
if only this.props.onValueChange
changed.Upvotes: 2