0

I have an array of strings which I would like to render as a list, with a colored text. The user can change the color with a button.

For that I have built a component called which receives an array and renders a list with the array's values and a button to change the color:

import React, { Component } from "react";

const renderArray = arr => (arr.map(value => (
    <li>
      {value}
    </li>
  )))


class List extends Component {
  constructor(props) {
    super(props);
    this.state = {
      color: 'red'
    }
  }
  toggleColor = () => {
    if (this.state.color === "red") {
      this.setState({color: "blue"});
    } else {
      this.setState({color: "red"});
    }
  }
  render() {
    const style = {
      color: this.state.color
    };
    return (
      <div style={style}>
        <ul>
          {renderArray(this.props.array)}
        </ul>
        <button onClick={this.toggleColor}>Change color</button>
      </div>
    );
  }
}
export default List;

The List is called with:

<List array={arr} />

And arr:

const arr = ['one', 'two', 'three'];

Fiddle here: Fiddle

But this seems incorrect to me. I rerender the whole array by calling renderArray() each time the color changes. In this case it is not too bad but what if the renderArray() is much more complex?

To my understanding, I need to create a new list only if the array prop changes and this could do in getDerivedStateFromProps (or in componentWillReceiveProps which will be deprecated...):

  componentWillReceiveProps(nextProps)
  {
    const renderedArray = renderArray(nextProps.array);
    this.setState({ renderedArray });
  }

And then, on render, use this.state.renderedArray to show the list.

But this seems strange, to store a rendered object in the state... Any suggestions?

Thanks!

2 Answers 2

2

1) React uses the concept of virtual DOM to calculate the actual difference in memory and only if it exists, render the difference into DOM

2) You can "help" React by providing a "key", so react will better understand if it's needed to re-render list/item or not

3) Your code componentWillReceiveProps can be considered as a bad practice because you're trying to make a premature optimization. Is repaint slow? Did you measure it?

4) IMHO: renderArray method doesn't make sense and can be inlined into List component

Sign up to request clarification or add additional context in comments.

Comments

0

React render the DOM elements efficiently by using a virtual DOM and checks if the update needs to happen or not and hence, it may not be an issue even if you render the list using props. To optimise on it, what you can do is to make use of PureComponent which does a shallow comparison of state and props and doesn't cause a re-render if nothing has changed

import Reactfrom "react";

const renderArray = arr => (arr.map(value => (
    <li>
      {value}
    </li>
  )))


class List extends React.PureComponent { // PureComponent
  constructor(props) {
    super(props);
    this.state = {
      color: 'red'
    }
  }
  toggleColor = () => {
    if (this.state.color === "red") {
      this.setState({color: "blue"});
    } else {
      this.setState({color: "red"});
    }
  }
  render() {
    const style = {
      color: this.state.color
    };
    return (
      <div style={style}>
        <ul>
          {renderArray(this.props.array)}
        </ul>
        <button onClick={this.toggleColor}>Change color</button>
      </div>
    );
  }
}
export default List;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.