你怎么能重构并使反应变得不那么笨重和可读性?

时间:2017-04-20 04:31:36

标签: javascript reactjs react-jsx

有没有办法让React代码如下面发布的组件更少笨重,更具可读性?我应该以某种方式将我的表数据分解成组件吗?只是想知道,因为我是新手,并认为这看起来不太好,但我不确定。非常感谢任何意见。

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);

1 个答案:

答案 0 :(得分:3)

您可以使用无状态功能组件。这些是React将作为组件呈现的常规函数​​。这非常适合使代码更小,更易读!

道具作为对象传入,因此您可以使用对象解构来访问特定属性:

// 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);