您如何重构并使 React 不那么笨重且更具可读性?
How can you refactor and make react less bulky and more readable?
有没有什么方法可以使 React 代码(例如我在下面发布的组件)不那么笨拙且更具可读性?我应该以某种方式将我的 table 数据分解成组件吗?只是想知道,因为我是新手,并且认为这看起来不太好,但我不确定。非常感谢任何输入。
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);
您可以使用无状态功能组件。这些是 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);
有没有什么方法可以使 React 代码(例如我在下面发布的组件)不那么笨拙且更具可读性?我应该以某种方式将我的 table 数据分解成组件吗?只是想知道,因为我是新手,并且认为这看起来不太好,但我不确定。非常感谢任何输入。
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);
您可以使用无状态功能组件。这些是 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);