初めに
- Reactでは,多くのデータを保持,変更し,動的なコンポーネントを表現している
- データの受取,代入,保持はReact独特な手法によって行われている
前提
基本: 数行レベルで綺麗なコードが書けること
1. 値の受け渡しは簡潔であるか
1-1. 受取:値をまとめて受け取る
const userInfo = {
username: 'Jnjdunk',
address: 'Tokyo',
favorite: 'Travel',
};
// NG
const username = userInfo.username;
const address = userInfo.address;
const favorite = userInfo.favorite;
// 🥴 Good
const { username, address, favorite } = userInfo;
1-2. 代入:プロパティ値の省略形を使えているか
// NG
const profile = {
username: username,
address: address,
favorite: favorite,
age: 88,
};
// 🥴 Good
// 変数のみを最初に記述,値をもつのは下に記述
const profile = {
username,
address,
favorite,
age: 88,
};
// 😎 Best
const age = 88;
const profile = {
...userInfo,
age,
};
2. 関数コンポーネントの方が可読性は高い
❗️あくまで綺麗さの観点
// NG クラスコンポーネント
class UserArea extends React.Component {
render() {
return <h1>Hello, {this.props.username}</h1>;
}
}
// 🥴 Good 関数コンポーネント
const UserArea = (props) => {
return <h1>Hello, {props.username}</h1>;
};
参照:Reactドキュメント
3. useEffectは複数書いても良い
無理に一つのuseEffect
の中に書く必要はない
// NG
useEffect(() => {
const getApi1 = async () => {
const response = await api('classinfo');
命令1(response);
};
const getApi2 = async () => {
const response = await api('userinfo');
命令2(response);
命令3(response);
};
getApi1();
getApi2();
}, []);
// 🥴 Good
// 1つ目
useEffect(() => {
const getApi = async () => {
const response = await api('classinfo');
命令1(response);
};
getApi();
}, []);
// 2つ目
useEffect(() => {
const getApi = async () => {
const response = await api('userinfo');
命令2(response);
命令3(response);
};
getApi();
}, []);
4. 少ないuseStateでデータを流す
// NG
// 記述ミスが起こりやすくなる
const [userId, setUserId] = useState();
const [userName, setUserName] = useState();
const [userAddress, setUserAddress] = useState();
const [userFavorite, setUserFavorite] = useState();
setUserId(props.userInfo.userid);
setUserName(props.userInfo.username);
setUserAddress(props.userInfo.address);
setUserFavorite(props.userInfo.favorite);
// 🥴 Good
const [userInfo, setUserInfo] = useState();
setUserInfo(props.userInfo);
// 😎 特定のキーに値を代入したいとき
const favorite = 'Eating';
setUserInfo((prevUserInfo) => ({ ...prevUserInfo, favorite }))
5. 使用するPropsの値の見える化
const userProfile = (props) => (
<Box>
{props.username}
<span>{props.address}</span>
</Box>
);
// 🥴 Good
const userProfile = ({ address, username }) => (
<Box>
{username}
<span>{address}</span>
</Box>
);
6. データ保持系はルール通りに使えているか
useContext, props, reduxそれぞれ単体だけでもアプリは実現できる.
それぞれの特性を理解して使うこと.
ルール例
-
useContext
は浅く広い階層のコンポーネントに適応- a) デフォルトStyle
- b) Header, Footer
- c) 何かの状態,on/off
- 独立させたいコンポーネントには,
props
を使用し,useContext
を利用しないこと- a) 依存関係が親の値のみになる
- b) 切り離し,他での利用が簡単になる
- 複雑なデータ変更パターンが多いとき, Reduxを使用する
7. Style方法 の使い分けはできているか
- 一つの記法で複雑なスタイリングを行うことは難しい
- Styleの使用ルールは明記されるべき
一例
7-1. CSS Module:基本はCSS/SCSSベースでデザインする
/* style.css */
.save_button {
color: white;
background: black;
}
// 書き方1
import styles from './style.css';
const buttonArea = () => {
return <Button style={style.save_button}>{text}</Button>;
};
// 書き方2
const buttonCn = "save_button";
const buttonArea = () => {
return <Button className={buttonCn}>{text}</Button>;
};
7-2. Inline CSS: 一部の動的な変更
const textStyle = {
display: isAdmin ? 'none' : 'block',
};
const textArea = () => {
return <div style={textStyle}>{text}</div>;
};
7-3. CSS In Js 変更できないクラス名のスタイルを動的に変更したいとき
外部コンポーネントなど,力ずく...
return (
<>
<style>
{`
.text {
color: ${props.color};
background: black;
}
`}
</style>
<div className='text'>{text}</div>
</>
);
応用編
最後に
良いコードは,コードの書き方だけではない.
様々な記法がある中で,プロジェクト内でStyle,データに関するルールが統一されていることはコードを理解する上で重要である.
良いコードの答えはない.
コードの綺麗さは「芸術的な観点」に近く,一つの正解があるわけではない.MaterialUI,Nextの公式ドキュメントで表現されている記法が正解ではなく,少なくとも,プロダクトに適した方法で保守性,移植性を考慮して追求することで,正解に近づけると考えている.