简体   繁体   中英

React: Use props or array of these

Could you tell me please. How can I make React component which I can use with props or with array of these props.

For example I have this component:

import React, { Component } from 'react'

export default class Links extends Component {
    render () {
        return (
            <a
                href={ this.props.link }
            >
                { this.props.name }
            </a>
        )
    }
}

And I want to use this component here:

import React, { Component } from 'react'
import Links from './Links'

export default class Block extends Component {
    render () {
        const social = [{
            name: 'Twitter',
            link: 'https://twitter.com',
        }, {
            name: 'FaceBook',
            link: 'https://fb.com',
        }]
        return (
            <div>
                <div>
                    <Links someword={ social }>
                </div>
                <Links name={ 'Google' } link={ 'https://google.com' }>
            </div>
        )
    }
}

Loop through your social array and map each value to your Links component and then put it in the render function of your Block component.

 export default class Block extends Component { render () { const social = [{ name: 'Twitter', link: 'https://twitter.com', }, { name: 'FaceBook', link: 'https://fb.com', }] const linkComps = social.map(e => <Links name={ e.name } link={e.link} key={e.name} />; ); return ( <div> <div> { linkComps } </div> <Links name={ 'Google' } link={ 'https://google.com' }> </div> ) } } 

You can use map to iterate the array and create the Links component. Since your social variable is having the const value, so instead of defining that inside render method, define it outside in the starting of the file.

Write it like this:

  const social = [{ name: 'Twitter', link: 'https://twitter.com', }, { name: 'FaceBook', link: 'https://fb.com', } ] class Block extends React.Component { render () { return ( <div> <div> { social.map((el,i) => <Links key={i} name={el.name} link={el.link} />) } </div> <Links name={ 'Google' } link={ 'https://google.com' }/> </div> ) } } class Links extends React.Component { render () { return ( <a href={ this.props.link } > { this.props.name } </a> ) } } ReactDOM.render(<Block/>, document.getElementById('app')) 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id='app'/> 

If you want to handle that inside Links component, you can write it like this, You can pass either an array by name array or pass the individual value by name and Link .

export default class Links extends Component {

    _renderLinks(){
        if(this.props.array && Array.isArray(this.props.array)){
            return this.props.array.map((el,i) => <a 
                                                     key={i} 
                                                     href={ el.link}
                                                  >  
                                                     {el.name} 
                                                  </a>
        }else{
            return <a href={ this.props.link}> {this.props.name} </a>
        }
    }

    render () {
        return (
            <div>
                {this._renderLinks()}
            </div>
        )
    }
}

The usual way to render multiple components from an array of props is with map :

render() {
  // ...
  return (
    <div>
      {social.map(props => (
        <Link key={props.link} {...props}/>
      ))}
    </div>
  );
}

That said, having a single component that takes two different kinds of props is, generally speaking, a bad idea. That is to say, a component should take eg name and link props or it should take an array of objects with those properties. It should not do both.

A clean way to solve your problem is to have two components: A <Link> component that takes name and link props and renders a single link, and a <Links> (plural) component that takes an array of objects with those properties and renders a <Link> (singular) component for each one.

A basic implementation looks like the below. Click on ▸⃝ Run code snippet below to see it in action (note that I added some CSS just to show the boundaries of each component).

 const Link = ({name, link}) => ( <a href={link}>{name}</a> ); const Links = ({links}) => ( <div> {links.map(props => <Link key={props.link} {...props}/>)} </div> ); class Block extends React.Component { render() { return ( <div> {/* Render an array of links with <Links> */} <Links links={this.props.social}/> {/* Render a single link with <Link> */} <Link name="Google" link="https://google.com"/> </div> ); } } const social = [ { name: 'Twitter', link: 'https://twitter.com', }, { name: 'Facebook', link: 'https://facebook.com', } ]; ReactDOM.render(<Block social={social}/>, document.querySelector('div')); 
 a {display: block;} div div {border: 1px dotted gray; padding: 5px; margin-bottom: 5px;} 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div></div> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM