Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
95 views
in Technique[技术] by (71.8m points)

ReactJs - Performance issue having a Parent-Child relationship between components

I am having a performance issue with a parent-child relationship with a big state. For the simplicity of my example, I did a simple code to illustrate the issue.

I am having a parent component that should manage the state and the child should only display the state of the parent component.

Here is my Parent Component :

class ParentComponent extends React.Component {
    constructor(props) {
        super(props);

        let elementsArray = [];

        for (let i = 0; i < 5000; i++) {
            elementsArray.push({
                key : i, value : i
            })
        }

        this.state = {
            elements : elementsArray
        };

        this.handleInputChange = this.handleInputChange.bind(this);
    }

    handleInputChange(key, value){
        let elements = [...this.state.elements];
        let element = {...elements[key]};
        element.value = value;
        elements[key] = element;
        this.setState({elements});
    }

    render() {
        return (
            <div >
                <ChildComponent
                    elements={this.state.elements}
                    handleInputChange={this.handleInputChange}
                />
            </div>
        )
    }
}

export default ParentComponent;

Here is the child component :

class ChildComponent extends React.Component {
    constructor(props) {
        super(props);
    }

    inputChange = (key, value) =>{
        this.props.handleInputChange(key, value);
    }

    render() {
        return (
            <div>
                {this.props.elements.map((element, i) =>{ 
                    return <div>
                        <input 
                            onChange={(event) => {this.inputChange(i, event.target.value)}}
                            value={element.value} key={i}/>
                    </div>
                })}
            </div>
        )
    }
}

export default ChildComponent;

Everytime I type a new value in one of the inputs of the child component, there is a latency of few secondes to set the new value. Is there anyway to maintain the state in the parent component and the update the state without having this delay?

Here is the sandbox of the code : https://codesandbox.io/s/frosty-glitter-7lyv3?fontsize=14&hidenavigation=1&theme=dark

question from:https://stackoverflow.com/questions/65853514/reactjs-performance-issue-having-a-parent-child-relationship-between-component

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Your console should have already warning about one thing: every child in an element must have a unique key. In your code:

                {this.props.elements.map((element, i) =>{ 
                    return <div>
                        <input 
                            onChange={(event) => {this.inputChange(i, event.target.value)}}
                            value={element.value} key={i} />
                    </div>
                })}

Should be:

                {this.props.elements.map((element, i) => ( 
                    <div key={i}>
                        <input 
                            onChange={(event) => {this.inputChange(i, event.target.value)}}
                            value={element.value} key={i} />
                    </div>
                )}

Note: key is an internal param used by React. Don't use it as a normal prop.

That will optimize a bit, but you are treating with a huge array and rendering it full. This is a lot of job done in handleInputChange and behind the scenes during render by React.

You can use some kind of onScroll event handler to render the data as it is shown. There are several options. Here a tutorial using InifiniteLoader.

Besides that, you'll need to optimize how data is saved. Modifying/recreating a thousands elements array (and an object!) on each key press does not sounds good. Either saving a different state for each element, or having a optimized setter.

Another kind of optimizations that may help is to avoid declaring functions inside the render. For example, on component mount, you can create an array of setters:

componentDidMount() {
   const inputHandlers = this.state.elements
     .map( (el, i) => this.handleInputChange.bind(this, i));
     // Or:
     // .map( (el, i) => (event) => this.handleInputChange(i, event.target.value));
   this.setState({inputHandlers});
}

//...
 <ChildComponent
   elements={this.state.elements}
   handleInputChange={this.inputHandlers}
 />

Then, in the child component:

<div>
  <input 
    onChange={ this.state.inputChange[i] }
    value={element.value}/>
</div>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...