Most efficient way of rendering JSX elements when iterating on array of data in React

后端 未结 8 1201
無奈伤痛
無奈伤痛 2020-12-09 17:42

I have an array which contains objects. I am creating a map of this array to renders the names with a span component.

let data = [{\"id\": \"01\         


        
相关标签:
8条回答
  • 2020-12-09 18:18

    The function toSpan can be reused.

    class App extends React.Component {
      render() {
        const data = [{id: `01`, name: `Hi`}, {id: `02`, name: `Hello`}]
        const toSpan = ({id, name}) => <span key={id}>{name}</span>
        return (
          <div>{data.map(toSpan)}</div>
        )
      }
    }
    
    0 讨论(0)
  • 2020-12-09 18:23

    I would do this

    const data = [{id: 1, name: 'a'}, {id: 2, name: 'b'}];
    
    export default class App extends PureComponent {
      render() {
        return (
          <div>
            {data.map(({ id, name }) => <span key={id}>{name}</span>)}
          </div>
        );
      }
    }
    

    Now, your data is not reinstantiated on every render, and you don't have to garbage collect any unnecessary variable declarations.

    0 讨论(0)
  • 2020-12-09 18:23

    the first method is correct. use the map function to iterate through the array.

    export default class App extends React.Component{
        constructor(props){
            super(props);
            this.state = {
              data: [{"id": "01", "name": "Hi"}, {"id": "02", "name": "Hello"}];
            };
     }
        render(){
            return(
                <div>           
                    {this.state.data.map((data,index)=>
                          <span key={data.id}>{data.name}</span>
                    )}             
            );
        }
    }

    0 讨论(0)
  • 2020-12-09 18:25

    Generally, for or while statement is the most efficient way to iterate an array. The way a small array is processed in non-critical place can be considered microoptimisation.

    The use of map is idiomatic in React components because it's fast enough and can return a value as a part of an expression.

    While this is an antipattern:

    let rows = [];
    data.map((key, i) => {
      rows.push(<span key={key.id}>{key.name}</span>);
    });
    

    map is supposed to map array elements to other values (hence the name), not to iterate an array instead of forEach or other loop. This problem can be tracked with ESLint array-callback-return rule.

    The component is stateless and doesn't need to be Component class. It can be functional component or PureComponent class. Since data is constant, it doesn't need to be assigned on each render:

    const data = [{"id": "01", "name": "Hi"}, {"id": "02", "name": "Hello"}];
    
    const App = props => <div>
      {data.map(({ id, name }) => <span key={id}>{name}</span>)}
    </div>;
    
    0 讨论(0)
  • 2020-12-09 18:26

    The first way is better.

    1. Array.prototype.map creates an array behind the scenes and returns it after applying the modification on each element. Functionality-1 creates two arrays, while Functionality-2 creates three.

    2. Functionality-1 reads better. It's how React code usually being written. For a simple element like this, I'd save the const definition for items and put the map statement in the JSX to be returned directly.

    0 讨论(0)
  • 2020-12-09 18:27

    I'd go with the map inside the return(...) as map returns an array. It's cleaner and readable, something I personally strive for.

    To add on to the answer, if the array data might change down the lane I'd go with creating a new stateless dump component:

    const Spanner = props => { return <span key={ props.data.id }>{ props.data.name }</span> };
    
    class App extends Component {
      render() {
        let data = [{"id": "01", "name": "Hi"}, {"id": "02", "name": "Hello"}];
          return (
            <div>
              { 
                data.map( (item, ind) => {
                  return (<Spanner key={item.id} data={item.name} />);
                })
              }
            </div>
          );
        }
      }
    }
    

    This way we can use this Spanner Component as a common component shared among different component. And in case the data changes over time ( which most of the time, does) you can write a wrapper function to the Spanner component and call the new function wherever required. data=[{"id": "01", "name": "Hi", "userType": "Admin"}, {"id": "02", "name": "Hello", "userType": "Client"}];

    const UserWidget = (props) => {
      return (
        <div>
          <h4>{ props.type }</h4>
          <Spanner key={ props.key } data={ props.name }/>
        </div>
      );
    }
    // now both the UserWidget and the Spanner Components can be used wherever required
    // say a dashboard Component wants to use the UserWidget
    class Dashboard extends Component {
      render() {
        let data = [{"id": "01", "name": "Hi", "userType": "Admin"}, {"id": "02", "name": "Hello", "userType": "Client"}];
          return (
            <div>
              { 
                data.map( (item, ind) => {
                  return (<UserWidget type={ item.userType } key={item.id} data={item.name} />);
                })
              }
            </div>
          );
        }
      }
    }
    

    This way you're not repeating yourself, and your App Component still has the expected behavior even if now the new data array has the new key userType. Again this is how I'd do it.

    0 讨论(0)
提交回复
热议问题