HOC(Higher-Order-Component)
class componentに置いてlife cycleなどの処理を共通化してラップしたもの
HOCではcomponentを直接変更してはいけない
直接変更することで、副作用を持たせてしまったり、再利用不可能なcomponentを返してしまうことになる
code: SampleHOC.jsx
function withSample(Component) {
return class extends React.Component {
constructor(props) {
super(props);
this.state = {
data: null
};
}
componentDidMount() {
fetchData().then(date => {
setState({ data });
});
}
render() {
return <Component data={this.state.data} {...this.props}/>
}
}
}
HOCの代わりにレンダープロップを使うことができる場面も多い。どちらを使うかは好みだが、レンダープロップを使う方が宣言的で良い気がする
レンダープロップとは、componentのpropsをしてrender関数を渡すもので、特定の処理を共通化したい場合に使うことが多い。
レンダープロップを使う代わりにchildrenも使うことができるので、条件に合うように変更していくのが良いと思われる
考える優先順位は次のようになるのかなと思う => children > render prop > HOC | Custom Hook
code: SampleRenderProp.jsx
// List component を使いまわしたいケース
const Sample = (props) => {
return <List render={item => <Item {...item}/>}/>;
};
const initialState = {fetching: false, data: []};
const reducer = (state, action) => {
switch(action.type) {
case "FETCHING":
return {...state, fetching: true};
case "ADD_DATA":
return {...state, data: action.data, fetching: false};
default:
return state;
}
}
const List = (props) => {
useEffect(() => {
const handleFetchData = async () => {
dispatch({type: "FETCHING"});
const data = await fetch();
dispatch({type: "ADD_DATA", data});
}
handleFetchData();
if(state.fetching) {
return <p>loading...</p>;
}
return (
<ul>
{state.data.map(item => {
return props.render(item);
})}
</ul>
);
}