06. State and Lifecycle - accgetter/React GitHub Wiki
ãã®ã»ã¯ã·ã§ã³ã§ã¯ãæ¬åœã«åå©çšã§ããã«ãã»ã«åãããã¯ããã¯ã³ã³ããŒãã³ãã®äœãæ¹ãåŠã³ãŸãããã
ã¿ã€ããŒãã»ããããïŒç§ããšã«æŽæ°ããŸãã
code:
function Clock(props) {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {props.date.toLocaleTimeString()}.</h2>
</div>
);
}
function tick() {
ReactDOM.render(
<Clock date={new Date()} />,
document.getElementById('root')
);
}
setInterval(tick, 1000);
ããããªãããæ¥µããŠéèŠãªèŠæ±: ã¿ã€ããŒã衚瀺UIãæŽæ°ãããã®Clockã®èŠçŽ ã¯ã¯ããã¯ã®è©³çްãšããŠã€ã³ããªã¡ã³ããŒã·ã§ã³ãã¹ãã§ããããšããããŠããŸãã
çæ³çã«ã¯ãäžåã®èšè¿°ã§Clockã³ã³ããŒãã³ããèªåã§æŽæ°ããŠæ¬²ããã§ãã
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
ãã®èŠæ±ãæºããããã«ã"state"ãClockã³ã³ããŒãã³ãã«å ããå¿
èŠããããŸãã
ã¹ããŒãã¯propsã«äŒŒãŠããŸãããããã¯éããããŠããŠå®å
šã«ã³ã³ããŒãã³ãã«ã³ã³ãããŒã«ãããŸãã
ã¯ã©ã¹ãšããŠå®çŸ©ãããã³ã³ãããŒã³ãã¯å¹Ÿã€ãã®ç¹åŸŽããããšè¿°ã¹ãŸããã
ããŒã«ã«ã®ã¹ããŒãã¯å³å¯ã«ã³ã³ããŒãã³ãã®ã¿ã§æå¹ãªæ©èœã§ãã
次ã®5ã¹ãããã§ãClockã®ãããªãã¡ã³ã¯ã·ã§ãã«ãªã³ã³ããŒãã³ããã¯ã©ã¹ã«ã³ã³ããŒãã§ããŸãã
- React.Componentãç¶æ¿ããES6 ã¯ã©ã¹ãåãååã§äœæãã
- render()ã¡ãœããã远å ããã
- ãã¡ã³ã¯ã·ã§ã³ã®äžèº«ãrender()ã¡ãœããã®äžã«ç§»ãã
- render()ã¡ãœããã®äžã§ãpropsãthis.propsã«ããã
- æ®ã£ã空ã®ãã¡ã³ã¯ã·ã§ã³ãåé€ããã
class Clock extends React.Component {
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.props.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
function tick() {
ReactDOM.render(
<Clock date={new Date()} />,
document.getElementById('root')
);
}
setInterval(tick, 1000);
Clockã¯ä»ããã¡ã³ã¯ã·ã§ã³ãšããããClassãšããŠå®£èšãããŠããŸãã ããã§ãããŒã«ã«ã¹ããŒããã©ã€ããµã€ã¯ã«ããã¯ãšããæ©èœã䜿ãããšãã§ããŸãã
æ¬¡ã®æé ã§ãæ¥ä»ãpropsããstateã«ç§»ããŸãã
- render()ã¡ãœããå ã®"this.props.date"ã"this.state.date"ã«å€æããŸãã
class Clock extends React.Component {
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
- initial this.state ãã¢ãµã€ã³ããã³ã³ã¹ãã©ã¯ã¿ãã¯ã©ã¹ã«è¿œå
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
Note ããŒã¹ã³ã³ã¹ãã©ã¯ã¿ã«propsãã©ã®ããã«æž¡ããŠããã
super(props);
ã¯ã©ã¹ã³ã³ããŒãã³ãã¯åžžã«ãããŒã¹ã³ã³ã¹ãã©ã¯ã¿ã«propsãæž¡ããŠåŒã¶å¿ èŠããããŸãã 3) date propsãèŠçŽ ããåé€ããŸãã
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
åŸã§ãã¿ã€ããŒã®codeãã³ã³ããŒãã³ãèªèº«ã«è¿œå ããŸãã çµæãšããŠãã®ããã«ãªããŸãã
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
次ã¯èªã1ç§ããšã«æéãæŽæ°ããClockã³ã³ããŒãã³ããäœã£ãŠãããŸããã
å€ãã®ã³ã³ããŒãã³ãã䌎ãã¢ããªã±ãŒã·ã§ã³ã§ã¯ã ã³ã³ããŒãã³ããç Žæ£ãããéã«ããã®ãªãœãŒã¹ãè§£æŸããããšããšãŠãéèŠã§ãã Clockã³ã³ããŒãã³ããæåã«æç»ãããæã¯å¿ ãã¿ã€ããŒãã»ãããããã§ãã Reactã§ã¯ããã"mounting"ãšåŒã³ãŸãã ãŸããClockã³ã³ããŒãã³ããçæããDOMãåé€ãããæã«ã¯ãã¿ã€ããŒãã¯ãªã¢ãããã§ãã Reactã§ã¯ããã"unmounting"ãšåŒã³ãŸãã
ã³ã³ããŒãã³ããmount, unmountããæã«ãã€ããã®ã³ãŒããå®è¡ããããã«ç¹å¥ãªã¡ãœãããå®çŸ©ããããšãã§ããŸãã
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
componentDidMount() {
}
componentWillUnmount() {
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
ãããã®ã¡ãœããã"lifecycle hooks"ãšåŒã³ãŸãã
componentDidMount() ã¯ã ã³ã³ããŒãã³ããDOMã«æç»ãããåŸã«ããã¯ããŸãã ã¿ã€ããŒãã»ããããã«ã¯ãšãŠãããå Žæã§ãã
componentDidMount() {
this.timerID = setInterval(
() => this.tick(),
1000
);
}
ã©ããã£ãŠtimer IDãä¿æããã this.props ã¯Reactããèªèº«ã«ã»ããã¢ãããããthis.state ã¯ç¹å¥ãªæå³ãæã£ãŠããããå¿ èŠã§ããã°æåã§ã¯ã©ã¹ã«ãã£ãŒã«ã(ãã®äŸã§ã¯timerId)ãèªç±ã«è¿œå ããŠãOK render()ã¡ãœããã§äœ¿ããªããªããstateã®äžã«ããå¿ èŠããããŸããã
ã¿ã€ããŒã¯componentWillUnmount() lifecycle hookã§åŒãåãããŸãããã
componentWillUnmount() {
clearInterval(this.timerID);
}
æåŸã«ãæ¯ç§å®è¡ãããtick()ã¡ãœãããå®è£ ããŸãã ããã¯ãã³ã³ããŒãã³ãã®ããŒã«ã«ã¹ããŒãã®ããã«this.setState()ã¡ãœããã§ãæŽæ°ã宿çã«ãããªã
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
componentDidMount() {
this.timerID = setInterval(
() => this.tick(),
1000
);
}
componentWillUnmount() {
clearInterval(this.timerID);
}
tick() {
this.setState({
date: new Date()
});
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
ããã§Clockã¯æ¯ç§æãå»ã¿ãŸãã
äœãè¡ãããããã¡ãœãããåŒã°ããé ã«æ¯ãè¿ã£ãŠã¿ãŸãããã
-
ãReactDOM.render()ãæž¡ãããæãReactãClockã³ã³ããŒãã³ãã®ã³ã³ã¹ãã©ã¯ã¿ãåŒã³ãŸããClackã¯çŸåšæå»ã衚瀺ããå¿ èŠããããŸãã®ã§ã ã³ã³ã¹ãã©ã¯ã¿ã¯ãçŸåšæå»ãæã€ãªããžã§ã¯ãã§this.stateãåæåããŸãã ãã®åŸãã®stateãæŽæ°ããŸãã
-
Reactã¯ããããClockã³ã³ããŒãã³ãã®render()ã¡ãœãããã³ãŒã«ããŸãã ããã¯Reactãç»é¢ã«äœã衚瀺ãã¹ããç¥ãæ¹æ³ã§ãã ãããŠReactã¯DOMãClockã³ã³ããŒãã³ããåºåããæå»è¡šç€ºã«æŽæ°ããŸãã
-
Clockã³ã³ããŒãã³ããDOMå ã«åºåããæãReactã¯"componentDidMount() lifecycle hook"ãåŒã³ãŸãã ãã®äžã§ãClockã³ã³ããŒãã³ãã¯ãã©ãŠã¶ã«1ç§ããšã«æãå»ãããã«ã¿ã€ããŒãã»ããããããšãèŠæ±ããŸãã
-
æ¯ç§ãã©ãŠã¶ã¯tick()ã¡ãœãããåŒã³ãŸãããã®äžã§ãçŸåšæå»ãæã£ããªããžã§ã¯ããsetState()ã¡ãœããã«æž¡ãããšã§Clockã³ã³ããŒãã³ãã¯UIãæŽæ°ããŸãã setState()ã¡ãœããããŸããŸã§ããReactã¯ç»é¢ãææ°ã§ããããã«ãstateã«å€åããããšrender()ã¡ãœãããåã³ã³ãŒã«ãããããšãç¥ã£ãŠããŸãã ä»åãrender()ã¡ãœããã®äžã®this.stete.dateã¯å€åããææ°ã®æéã衚瀺ãããŸããReactãDOMãé©åã«æŽæ°ããã®ã§ãã
-
ããClockã³ã³ããŒãã³ããDOMããåé€ãããããReactã¯ã¿ã€ããŒãã¹ãããããããã«ã"componentWillUnmount() lifecycle hook"ãã³ãŒã«ããŸãã
setState() ã¡ãœããã«ã€ããŠ3ã€ç¥ã£ãŠããã¹ãããšããããŸãã
äŸãã°ãããã¯ã³ã³ããŒãã³ããåæç»ããŸãã:
// Wrong
this.state.comment = 'Hello';
代ããã«setState()ã䜿ã£ãŠãã ãã:
// Correct
this.setState({comment: 'Hello'});
this.stateã«å€ãä»£å ¥ã§ããã®ã¯ã³ã³ã¹ãã©ã¯ã¿ã®ã¿ã§ãã
Reactã¯ããã©ãŒãã³ã¹ã®ãããè€æ°ã®setState()ã®åŒã³åºããäžã€ã®æŽæ°ã«ãŸãšããããã§ãã this.propsãšthis.steteéåæçã«æŽæ°ãããã®ã§ã stateã®å€ã䜿ã£ãŠæ°ããªstateãäœããããªèšç®ã¯ãã¹ãã§ã¯ãªãã§ãã äŸãã°ã次ã®ã³ãŒãã¯ã«ãŠã³ã¿ãŒãæŽæ°ããã«ã¯å€±æããŸã:
// Wrong
this.setState({
counter: this.state.counter + this.props.increment,
});
ããã解決ããããã«ã¯ãfanctionãåãåããsetStateã®2ã€ç®ã®åœ¢åŒã䜿ããŸãããã ãã®funcitionã¯ç¬¬äžåŒæ°ã«äºåã®stateãåãåã, ãã®æã®propsã第äºåŒæ°ãšããŠåãåããŸã:
// Correct
this.setState((prevState, props) => ({
counter: prevState.counter + props.increment
}));
äžèšã§ã¯ãarrow颿°ã䜿ã£ãŠããŸããéåžžã®é¢æ°ã§ãOKã§ã:
// Correct
this.setState(function(prevState, props) {
return {
counter: prevState.counter + props.increment
};
});
setState()ãåŒã¶æãReactã¯current stateã«æäŸãããªããžã§ã¯ããããŒãžããŸãã äŸãã°ãstateã¯å¹Ÿã€ãã®ç¬ç«ããå€ãå«ãã§ããŸã:
constructor(props) {
super(props);
this.state = {
posts: [],
comments: []
};
}
ãããŠãsetState()ãåé¢ããŠã³ãŒã«ããããããç¬ç«ããŠæŽæ°ããããšãã§ããŸã:
componentDidMount() {
fetchPosts().then(response => {
this.setState({
posts: response.posts
});
});
fetchComments().then(response => {
this.setState({
comments: response.comments
});
});
}
ããŒãžã¯æµ ãéå±€ã§ããããã£ãŠãthis.setState({comments}) ã¯this.state.postsããã®ãŸãŸæ®ããŸãããthis.state.commentsã¯å®å šã«çœ®ãæããããŸãã
芪ã³ã³ããŒãã³ããåã³ã³ããŒãã³ãããç¹å®ã®ã³ã³ããŒãã³ããstatefulãstatelessãã©ããç¥ãããšãã§ããã ãããã¯ããããfuncionãªã®ãclassãªã®ãæ°ã«ããå¿ èŠããããŸããã ããã¯stateã倧æµããŒã«ã«ã§åŒã°ããããã«ãã»ã«åãããããã§ãã ãããææãèšå®ããèªåèªèº«æå€ã®ã³ã³ããŒãã³ãã«ã¯ã¢ã¯ã»ã¹ã§ããŸããã ã³ã³ããŒãã³ãã¯ãstateãåã³ã³ããŒãã³ãã®propsãšããŠæž¡ãããšãéžæã§ããŸã:
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
ããã¯ãŠãŒã¶å®çŸ©ã®ã³ã³ããŒãã³ãã§ããŸã广ããããŸã:
<FormattedDate date={this.state.date} />
ãã®FormattedDateã³ã³ããŒãã³ãã¯ãèªåã®propsããæ¥ä»ãåãåãããããClockã³ã³ããŒãã³ãã®stateããpropsããŸãã¯ãæã§ã¿ã€ãããããããã©ããã¯ç¥ãããšã¯ãªãã§ããã:
function FormattedDate(props) {
return <h2>It is {props.date.toLocaleTimeString()}.</h2>;
}
ããã¯äžè¬ã«"top-down" data flow ã "unidirectional" data flow ãšåŒã°ããŸããäžæ¹åãšããæå³ã§ãã ããããstateãåžžã«å¹Ÿã€ãã®æç¢ºãªã³ã³ããŒãã³ãã«ææããããããã®stateããæŽŸçããããŒã¿ãŸãUIã¯ãäžå±€ã³ã³ããŒãã³ãã ãã«åœ±é¿ãäžããŸãã
If you imagine a component tree as a waterfall of props, each component's state is like an additional water source that joins it at an arbitrary point but also flows down.
To show that all components are truly isolated, we can create an App component that renders three s:
ããã³ã³ããŒãã³ãã®éå±€ããpropsã®ãŠã©ãŒã¿ãŒãã©ãŒã«ãšã€ã¡ãŒãžãããšãããããã®ã³ã³ããŒãã³ãã®stateã¯å¥œããªæã«è¿œå ãããæ°Žæºã®ãããªãã®ã§ã ããããŸããäžã«èœã¡ãŠãããŸãã
ãã¹ãŠã®ã³ã³ããŒãã³ããæ¬åœã«ç¬ç«ããŠããã®ãèŠãããã«ã3ã€ã®Clockã³ã³ããŒãã³ããæç»ããã¢ããªãäœã£ãŠã¿ãŸãããã
function App() {
return (
<div>
<Clock />
<Clock />
<Clock />
</div>
);
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
ããããã®Clockã¯èªåèªèº«ã®ã¿ã€ããŒãã»ãããç¬ç«ããŠæŽæ°ããŠããŸãã React ã®ã¢ããªã±ãŒã·ã§ã³ã§ã¯ãã³ã³ããŒãã³ããã¹ããŒããã«ããåŠãã«ããããããåŸã ã«å€åããã ããã³ã³ããŒãã³ãã®éçºãšæããŸãã éããããã§ãã