简体   繁体   中英

How can you refactor and make react less bulky and more readable?

Is there any way to make React code such as the component I've posted below less clunky and more readable? Should I break out my table data into components somehow? Just wondering, as I'm new to this, and think that this doesn't look great, but I'm not sure. Thanks so much for any input.

class Profile extends Component {

    componentWillMount() {
        const { id } = this.props.match.params;
        this.props.getStarshipsData(id);
    }

    successfulLoad(itemStatus) {
        return (itemStatus === 'SUCCESS');
    }

    findPersonById(people, idNumber) {
        return people.filter(person => {
            return person.url === `http://swapi.co/api/people/${idNumber}/`;
        });
    }

    renderLoadingMessage() {
        if (!this.successfulLoad(this.props.starships.status)) {
            return <p id="loading-text">{ 'Loading' }</p>;
        }
        return null;
    }

    renderTable() {
        if (this.successfulLoad(this.props.starships.status)) {
            return (
                <table id="starship-data-table">
                    <tbody>
                        <tr>
                            <th className="starship-data-header">Name</th>
                            <th className="starship-data-header">Model</th>
                            <th className="starship-data-header">Length</th>
                            <th className="starship-data-header">Cost in Credits</th>
                            <th className="starship-data-header">Crew</th>
                            <th className="starship-data-header">Hyperdrive Rating</th>
                        </tr>
                        { this.renderStarships() }
                    </tbody>
                </table>
            );
        }
        return null;
    }

    renderStarships() {
        if (this.successfulLoad(this.props.starships.status)) {
            const { starships } = this.props.starships.data;
                return (
                    starships.map((starship, index) => {
                        return (
                            <tr key={index} className="starship-container">
                                <td className="starship-data">{starship.name}</td>
                                <td className="starship-data">{starship.model}</td>
                                <td className="starship-data">{starship.length}</td>
                                <td className="starship-data">{starship.cost_in_credits}</td>
                                <td className="starship-data">{starship.crew}</td>
                                <td className="starship-data">{starship.hyperdrive_rating}</td>
                            </tr>
                        );
                    })
                );
        }
        return;
    }

    render() {
        const { id } = this.props.match.params;
        const { people } = this.props.people.data;
        const person = this.findPersonById(people, id)[0];

        return (
            <div id="profile-page">
                <div id="profile-attributes-container">
                    <div id="profile-picture-name">
                        <p className="profile-attribute">{ person.name } </p>
                        <img id="profile-picture" role="presentation" src={profilePicture} />
                    </div>
                    <div id="profile-row-1">
                        <p className="profile-attribute"> Hgt: { person.height } </p>
                        <p className="profile-attribute"> Mass: { person.mass } </p>
                        <p className="profile-attribute"> Hair: { person.hair_color } </p>
                    </div>
                    <div id="profile-row-2">
                        <p className="profile-attribute"> Eyes: { person.eye_color } </p>
                        <p className="profile-attribute"> Born: { person.birth_year } </p>
                        <p className="profile-attribute"> Gen: { person.gender } </p>
                    </div>
                </div>
                <div id="starships-info">
                    <img id="starships-title" role="presentation" src={spaceship} />
                    <div id="starships-table">
                    { this.renderTable() }
                    { this.renderLoadingMessage() }
                    </div>
                </div>
            </div>
        );
    }
}

const mapStateToProps = state => {
    const { starships, people } = state;
    return { starships, people };
};

const mapDispatchToProps = dispatch => {
    return {
        getStarshipsData: starships => {
            dispatch(starshipsActions.getStarshipsData(starships));
        },
    };
};

export default connect(mapStateToProps, mapDispatchToProps)(Profile);

You can use stateless functional components. These are normal functions that React will render as components. This is great for making code smaller and more readable!

The props are passed in as an object, so you can use object destructuring to access specific properties:

// returns a loading message
const LoadingMessage = ({message}) =>
  <p id="loading-text">{ message }</p>


// returns a <tbody> containing a row for each starship
const StarshipTableRows = ({starships}) =>
  <tbody>
    starships.map((starship, index) => 
      <tr key={index} className="starship-container">
        ['name', 'model', 'length', 'cost_in_credits', 'crew', 'hyperdrive_rating']
          .map(key => <td className="starship-data">{starship[key]}</td>)
      </tr>);
  </tbody>


// returns a <thead> containing headers for the table
const StarshipTableHeaders = () =>
  <thead>
    <tr>
      ['Name', 'Model', 'Length', 'Cost in Credits', 'Crew', 'Hyperdrive Rating']
        .map(key => <th className="starship-data-header">{key}</td>)
    </tr>
  </thead>


// returns a <table> containing starships
const StarshipTable = ({starships}) =>
  <table id="starship-data-table">
   <StarshipTableHeaders />
   <StarshipTableRows starships={starships.data} />
  </table>


// returns a profile page
const ProfilePage = ({person, profilePicture, spaceship, starships, successfulLoad}) => 
  <div id="profile-page">
    <div id="profile-attributes-container">
      <div id="profile-picture-name">
        <p className="profile-attribute">{ person.name } </p>
        <img id="profile-picture" role="presentation" src={profilePicture} />
      </div>
      <div id="profile-row-1">
        <p className="profile-attribute"> Hgt: { person.height } </p>
        <p className="profile-attribute"> Mass: { person.mass } </p>
        <p className="profile-attribute"> Hair: { person.hair_color } </p>
      </div>
      <div id="profile-row-2">
        <p className="profile-attribute"> Eyes: { person.eye_color } </p>
        <p className="profile-attribute"> Born: { person.birth_year } </p>
        <p className="profile-attribute"> Gen: { person.gender } </p>
      </div>
    </div>
    <div id="starships-info">
      <img id="starships-title" role="presentation" src={spaceship} />
      <div id="starships-table">
        { 
          successfulLoad
          ? <StarshipTable starships={starships} />
          : <LoadingMessage message="loading" />
        }
      </div>
    </div>
  </div>

const mapStateToProps = state => {
  const { starships, people } = state;
  return { starships, people };
};

const mapDispatchToProps = dispatch => {
  return {
      getStarshipsData: starships => {
          dispatch(starshipsActions.getStarshipsData(starships));
      },
  };
};

class Profile extends Component {

  componentWillMount() {
    const { id } = this.props.match.params;
    this.props.getStarshipsData(id);
  }

  findPersonById(people, idNumber) {
    return people.filter(person => 
      person.url === `http://swapi.co/api/people/${idNumber}/`;
    );
  }

  render() {
    const { id } = this.props.match.params;
    const { people } = this.props.people.data;
    const person = this.findPersonById(people, id)[0];
    const starships = this.props.starships;
    const successfulLoad = starships.status === 'SUCCESS';

    return <ProfilePage 
      person={person} 
      successfulLoad={successfulLoad} 
      starships={starships} 
      spaceship={null} 
      profilePicture={null}/>;
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(Profile);

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