ããã«ã¡ã¯ 9æ24ã25æ¥ã«ãHolyJsããã³ããšã³ãéçºè
ã®äŒè°https://holyjs-moscow.ru/ãã¢ã¹ã¯ã¯ã§éå¬ãããŸããã ç§ãã¡ã¯ãã¯ã€ãºãéå¬ããã¹ã¿ã³ãã§äŒè°ã«æ¥ãŸããã ã¡ã€ã³ã¯ã€ãºããããŸãã-äºéž4ã©ãŠã³ããšæçµã©ãŠã³ã1ã§ãApple WatchãšLegoã®ã³ã³ã¹ãã©ã¯ã¿ãŒããã¬ã€ãããŸããã ãŸããåå¥ã«ãåå¿ç¥èã¯ã€ãºãå®æœããŸããã
katã®äž-åå¿æã®ã¯ã€ãºã¿ã¹ã¯ã®è§£æã æ£ãããªãã·ã§ã³ã¯ãã¿ãã¬ã®äžã«é ãããã®ã§ãåæãèªãããšãã§ããã ãã§ãªããèªåèªèº«ããã§ãã¯ããããšãã§ããŸã:)
è¡ããïŒ
䟿å®äžã質åãã»ã¯ã·ã§ã³ã«ã°ã«ãŒãåããŸããã
ã»ã¯ã·ã§ã³1. this.setStateã®æäœã®åºæ¬çãªç解ãšã³ã³ããŒãã³ãã®ã©ã€ããµã€ã¯ã«ã®æŽæ°ïŒ
質å1ã
react-: 1) SetProps, SetState, ForceUpdate 2) ForceUpdate, SetState 3) ForceUpdate, SetState, Parent (re)render 4) ForceUpdate, SetState, directly call UpdateComponent
çã3ïŒForceUpdateãSetStateãParentïŒreïŒrender
質å2ã
, this.setState({}) react 1) , updating lifecycle 2) , 3) React "Object cannot be empty" 4) state
çã1ïŒã³ã³ããŒãã³ãã¯ããŒãã£ãšããŒã¯ãããæŽæ°ã©ã€ããµã€ã¯ã«ãåŒã³åºãããŸã
質å1ãš2ã®åæ質åã«çããããã«ã2ã€ã®éšåãåæããŸãã
1ïŒæŽæ°ãµã€ã¯ã«ã«å¯Ÿããç¬èªã®ã³ã³ããŒãã³ãèŠæ±
2ïŒã³ã³ããŒãã³ãå€ã®ãªã¯ãšã¹ã
ã³ã³ããŒãã³ãèªäœã«ã¯ãèªèº«ãæŽæ°ãã2ã€ã®æ¹æ³ããããŸãã
1ïŒthis.setStateããã³this.forceUpdateã ãã®å Žåãã³ã³ããŒãã³ãã¯ããŒãã£ãšããŠããŒã¯ãããã調æŽããã§ãã¯ã§ãã¬ã³ããªã³ã°ã®åªå
é äœã«ããå ŽåãæŽæ°ãµã€ã¯ã«ãéå§ãããŸãã
èå³æ·±ãäºå®ïŒ this.setState({})
ãšthis.forceUpdate
ã¯ç°ãªããŸãã this.setState({})
ãåŒã³åºããããšãshouldComponentUpdateã¡ãœãããªãã§æŽæ°ã«ãŒããéå§ãããthis.forceUpdate
ãšã¯ç°ãªããå®å
šãªæŽæ°ã«ãŒããåŒã³åºãããŸãã this.setState({})
ã®äŸã¯ã https ïŒ//codesandbox.io/s/m5jz2701l9ã«ãããŸã ïŒäŸã§setStateãforceUpdateã«çœ®ãæãããšãã³ã³ããŒãã³ãã®åäœãã©ã®ããã«å€åãããã確èªã§ããŸãïŒã
2ïŒã³ã³ããŒãã³ãã®èŠªãåã¬ã³ããªã³ã°ããããšãvDOMããŒããæŽæ°ãå¿
èŠãªãã¹ãŠã®åãè¿ããããããã¯å®å
šæŽæ°ã©ã€ããµã€ã¯ã«ãšãåŒã°ããŸãã shouldComponentUpdateãèšè¿°ããããã³ã³ããŒãã³ããPureComponentãšããŠå®çŸ©ããããšã«ããããµãããªãŒã®å®å
šãªåã«ãŠã³ããåé¿ã§ããŸãã
質å3
Component PureComponent (PC) 1) Component , Pure 2) PC SCU, shallowEqual props state 3) PC , store 4) PC shouldComponentUpdate
åçãšè§£æ2ïŒPCã¯SCUãå®è£
ããshallowEqualãããããšã¹ããŒããå®è¡ããŸã
åã«èª¬æããããã«ã芪ãïŒåïŒã¬ã³ããªã³ã°ãããšããµãããªãŒå
šäœãæŽæ°ã©ã€ããµã€ã¯ã«ã«éä¿¡ãããŸãã ã«ãŒãèŠçŽ ãæŽæ°ãããšæ³åããŠãã ããã ãã®å Žåãé£éå¹æã«ãããšãåå¿ããªãŒã®ã»ãŒå
šäœãæŽæ°ããå¿
èŠããããŸãã äžèŠãªæŽæ°ãæé©åããŠéä¿¡ããªãããã«ããã«ã¯ã shouldComponentUpdate
ã¡ãœããããããã³ã³ããŒãã³ããæŽæ°ããå¿
èŠãããå Žåã¯trueãè¿ããããã§ãªãå Žåã¯falseãè¿ãããšãã§ããŸãã reactã§ã®æ¯èŒãç°¡åã«ããããã«ã PureComponent
ããç¶æ¿ããŠããã«åç
§ã§ããPureComponent
ãååŸã§ãshouldComponentUpdate
ãããã¯ãåç
§ïŒãªããžã§ã¯ãåã«ã€ããŠèª¬æããŠããå ŽåïŒãŸãã¯å€ïŒå€åã«ã€ããŠèª¬æããŠããå ŽåïŒã«ãã£ãŠãã³ã³ããŒãã³ãã«å
¥ããã¹ãŠã®shouldComponentUpdate
ãšç¶æ
ãæ¯èŒããŸãã
質å4ã
this.setState(() => {}, () => {}) â setState? 1) set . updating 2) state 3) setState 1
åçãšè§£æ2ïŒ2çªç®ã®é¢æ°ã¯ãç¶æ
ã®æŽæ°åŸã«åŒã³åºãããŸã
Reactã©ã€ããµã€ã¯ã«ã«ã¯ãããŠã³ãã«ãŒãçšã®componentDidMountãšæŽæ°çšã®componentDidMount
2ã€ã®ã¡ãœããããããã³ã³ããŒãã³ãã®æŽæ°åŸã«ããžãã¯ãè¿œå ã§ããŸãã ããšãã°ãhttpãªã¯ãšã¹ããäœæããã¹ã¿ã€ã«ãå€æŽããhtmlèŠçŽ ã®ã¡ããªãã¯ãååŸããïŒæ¡ä»¶ã«ããïŒsetStateãäœæããŸãã ç¶æ
ã®ç¹å®ã®ãã£ãŒã«ããå€æŽããåŸã«äœããã®ã¢ã¯ã·ã§ã³ãå®è¡ããå Žåã componentDidUpdate
ã¡ãœããã§æ¯èŒãèšè¿°ããå¿
èŠããããŸãã
componentDidUpdate(prevProp, prevState) { if (prevState.foo !== this.state.foo) { // do awesome things here } }
ãŸãã¯ãsetStateã§å®è¡ã§ããŸãã
setState( // set new foo {foo: 'baz'}, () => { // do awesome things here } );
ããããã®æ¹æ³ã«ã¯é·æãšçæããããŸãïŒããšãã°ãè€æ°ã®å Žæã§setStateãå€æŽããå Žåãæ¡ä»¶ã1åèšè¿°ããæ¹ã䟿å©ãªå ŽåããããŸãïŒã
質å5ã
render: class A extends React.PureComponent { render() { console.log('render'); return <div /> } } function Test() { return <A foo='bar' onClick={() => console.log('foo')} /> } const rootElement = document.getElementById("root"); ReactDOM.render(<Test />, rootElement); setTimeout(() => ReactDOM.render(<Test />, rootElement)); 1) 1 2) 2 3) 3 4) 0
質å6ã
render: class A extends React.PureComponent { render() { console.log('render'); return <div /> } } function Test() { return <A foo='bar' /> } const rootElement = document.getElementById("root"); ReactDOM.render(<Test />, rootElement); setTimeout(() => ReactDOM.render(<Test />, rootElement)); 1) 1 2) 2 3) 3 4) 0
質å7ã
render: class A extends React.PureComponent { componentDidMount() { console.log('render'); } render() { return <div /> } } const rootElement = document.getElementById("root"); ReactDOM.render(<A />, rootElement); setTimeout(() => ReactDOM.render(<A />, rootElement)); 1) 1 2) 2 3) 3 4) 0
質å5-7ã®åæ質å5â7åãããšãå¿
èŠã§ãPureComponent
ã®åäœã®ç解ãšãå°éå
·ã®è»¢éæã®ã³ã³ããŒãã³ãã®æŽæ°ã確èªããããã§ãã renderã¡ãœããå
ã§jsxã³ãŒã«ããã¯ãæž¡ãããããrenderé¢æ°ã§çŽæ¥èšè¿°ããå ŽåïŒ
render () { return <Button onClick={() => {}} />; }
次ã«ã芪ã®åã¬ã³ããªã³ã°ã¯ããã®ã¯ãªãã¯ãã³ãã©ãŒãæŽæ°ããŸãã ããã¯ãåã¬ã³ããªã³ã°ãäžæã®ãªã³ã¯ãæã€æ°ããé¢æ°ãäœæããããã«çºçããŸããPureComponentã§æ¯èŒãããšãæ°ããå°éå
·ãå€ãå°éå
·ãšçãããªããããã³ã³ããŒãã³ããæŽæ°ããå¿
èŠããããŸãã ãã¹ãŠã®ãã§ãã¯ã«åæ ŒããshouldComponentUpdateãfalseãè¿ãå ŽåãæŽæ°ã¯è¡ãããŸããã
ã»ã¯ã·ã§ã³2. Reactã®ããŒ
ããã§ããŒã®è©³çŽ°ãªåæãå
¬éããŸããïŒ https : //habr.com/company/hh/blog/352150/
質å1ã
key, ? 1) key 2) updating lifecycle 3) key 4) reconciliation
åçãšè§£æ1ïŒããŒãå€æŽãããšãã«ã以åã®ã€ã³ã¹ã¿ã³ã¹ãåé€ããæ°ããã€ã³ã¹ã¿ã³ã¹ãããŠã³ãããŸã
ããŒã䜿çšããªãå Žåãreactã¯ãã¢ã®èŠçŽ ã®ãªã¹ããäžããäžãžæ¯èŒããŸãã ããŒã䜿çšãããšã察å¿ããããŒã§æ¯èŒãè¡ãããŸãã æ°ããããŒãåºçŸããå Žåããã®ãããªã³ã³ããŒãã³ãã¯èª°ãšãæ¯èŒããããããã«ãŒãããäœæãããŸãã
èŠçŽ ã1ã€ã§ããã®ã¡ãœããã䜿çšã§ããŸãã <A key="1" />
èšå®ã§ããŸãã次ã®ã¬ã³ããªã³ã°ã§ã¯<A key="2" />
ãæå®ããŸãããã®å Žåãreactã¯<A key="1" />
ãåé€ã<A key="1" />
ãããŠãæåãã<A key="2" />
ãäœæããŸãã
質å2ã
this.prop.key? 1) 2) 3) static getKey
åçãšè§£æ2ïŒããã
ã³ã³ããŒãã³ãã¯ãå°éå
·ãšããŠæž¡ãããåããããŒãåŠç¿ã§ããŸãããããŒã«ã€ããŠã¯åŠç¿ã§ããŸããã
質å3ã
render: class A extends React.PureComponent { componentDidMount() { console.log('render'); } render() { return <div /> } } const rootElement = document.getElementById("root"); ReactDOM.render(<A key='1' />, rootElement); setTimeout(() => ReactDOM.render(<A />, rootElement)); 1) 1 2) 2 3) 3 4) 0
åçãšè§£æ2ïŒ2
ããŒãå€æŽãããšãã³ã³ããŒãã³ããåäœæããããããã¬ã³ããªã³ã°ã2å衚瀺ãããŸãã
ã»ã¯ã·ã§ã³3. jsxã«é¢ãã質å
質å1ã
. 1) prop / context 2) 3) setParentProps 4) static getParentRef
åçãšè§£æ1ïŒprop / contextã®åœ¢åŒã§ã®ã³ãŒã«ããã¯
2ïŒã¢ãã«ã®ã¬ã€ã€ãŒãåé€ããäœæ¥ãé²ãã
æ£è§£ã¯2ã€ãããŸãã ã¯ã€ãºã§ãããã®ãããããéžæãããšããã€ã³ããã«ãŠã³ããããŸãã ãã®è³ªåã¯ãããŒã¿ãããŒãªã¢ã¯ã·ã§ã³ã®ç¥èã®ããã®ãã®ã§ãã äžããäžãžã®ããŒã¿ã¯ãå°éå
·ãŸãã¯ã³ã³ããã¹ãã®åœ¢ã§é
åžãããã³ãŒã«ããã¯ãå«ããããšãã§ããŸããã³ãŒã«ããã¯ã¯ã以äžã®ã³ã³ããŒãã³ããåŒã³åºããŠã·ã¹ãã ã®ç¶æ
ã«åœ±é¿ãäžããããšãã§ããŸãã
ã¢ãã«ã®åé€ïŒã³ã³ããã¹ããšããããïŒãçµã¿åãããå¥ã®æ¹æ³ã¯ãããšãã°ãreact-reduxãã€ã³ãã£ã³ã°ã§ãã
ãã®ã©ã€ãã©ãªã¯ãreactïŒreduxïŒãã掟çããã¢ãã«ã䜿çšããŸãã ãããã€ããŒã«redux.storeãèšå®ããŸããå®éã«ã³ã³ããã¹ãã«ã¹ãã¢ãèšå®ããŸãã 次ã«ãéçºè
ã¯HOCæ¥ç¶ã䜿çšããŸããããã¯ã³ã³ããã¹ãã«å
¥ããã¹ãã¢ã«å€æŽãç»é²ïŒstore.subscribeïŒããã¹ãã¢ãå€æŽããããšmapStateToProps
é¢æ°ãåmapStateToProps
ãŸãã ããŒã¿ãå€æŽãããŠããå Žåãå°éå
·ã§ããããã©ããããããªããžã§ã¯ãã«èšå®ããŸãã
åæã«ãconnectã䜿çšãããšãéçºè
ãã³ã³ããŒãã³ãã«æž¡ãå¿
èŠã®ããactionCreatorãæå®ããmapDispatchToProps
ãæå®ã§ããŸãã 次ã«ãå€éšããïŒã³ã³ããã¹ããªãã§ïŒããããåãåãã actionCreators
ãã¹ãã¢ã«ãã€ã³ããïŒ actionCreators
ã§ã©ããããŸãïŒãããããå°éå
·ãšããŠã©ãããããã³ã³ããŒãã³ãã«æž¡ããŸãã
質å2ã
props jsx? 1) 2) children
åçãšè§£æ1ïŒä»»æã®
ä»»æã«è»¢éã§ããŸãã äŸïŒ
<Button icon={<Icon kind='warning'/>}></Button>
ã¢ã€ã³ã³ä»ãã®ãã¿ã³ãæç»ããŸãã ãã®ã¢ãããŒãã¯ã1ã€ã®åã®å°éå
·ãæŽçããã®ã§ã¯ãªããã³ã³ããŒãã³ãã«ããŸããŸãªèŠçŽ ã®çžå¯Ÿäœçœ®ãå¶åŸ¡ããæš©å©ãæ®ãããã«äœ¿çšãããšéåžžã«äŸ¿å©ã§ãã
ã»ã¯ã·ã§ã³4. setStateã®é«åºŠãªç解
匷ãé¢é£ãã3ã€ã®è³ªåã次ã«ç€ºããŸãã
質å1ã
this.state = {a: 'a'}; ... this.setState({a: 'b'}); this.setState({a: this.state.a + 1}) this.state? 1) {a: 'a1'} 2) {a: 'b1'} 3) 4) {a: 'a'}
質å2ã
this.state={a: 'a'} ... this.setState({a: 'b'}) this.setState(state => ({a: state.a + 1})) this.state? 1) {a: 'a1'} 2) {a: 'b1'} 3) 4) {a: 'ab1'}
質å3ã
2 setState componentDidUpdate updating lifecycle 1) 1 2) 2 3) 3 4)
質å1ã3ã®åæsetStateã®ãã¹ãŠã®äœæ¥ã¯ãããã§å®å
šã«èª¬æãããŠããŸãã
1ïŒ https://reactjs.org/docs/react-component.html#setstate
2ïŒ https://stackoverflow.com/questions/48563650/does-react-keep-the-order-for-state-updates/48610973#48610973
å®éã«ã¯ãsetStateã¯åæçã«çºçããŸããã
ãŸããreact-lifecycleã¡ãœãããreact-eventã®ãã³ãã©ãŒé¢æ°ïŒonChangeãonClickïŒå
ã«ãããã©ããã«å¿ããŠãsetStateã®åŒã³åºããé£ç¶ããŠè€æ°ããå ŽåãsetStateã®å®è¡ã¯ç°ãªããŸãã
SetStateã¯ãreactãã³ãã©ãŒå
ã§ãããã§åäœããŸãïŒåŒã³åºãã¹ã¿ãã¯å
ã®ãŠãŒã¶ãŒå®çŸ©é¢æ°ãçµäºããã€ãã³ããã³ãã©ãŒãšã©ã€ããµã€ã¯ã«ã¡ãœãããåŒã³åºããé¢æ°ã«å
¥ããšãå€æŽãããŒã«ããã¯ãããŸãïŒã ãããã¯æ¬¡ã
ã«å転ãããããåå¿ãã³ãã©å
ã«ããå Žåã次ã®ããã«ãªããŸãã
this.state = {a: 'a'}; // a: 'a' ... this.state.a // a: 'a' this.setState({a: 'b'}); // a: 'b' + . this.state.a // a: 'a' this.setState({a: this.state.a + 1}) // a: 'a1'
å€æŽãbatchevoã§çºçããããã
ãããåæã«ãreset-handlersã®å€éšã§setStateãåŒã³åºãããå ŽåïŒ
this.state = {a: 'a'}; // a: 'a' ... this.state.a // a: 'a' this.setState({a: 'b'}); // a: 'b' + this.state.a // a: 'b' this.setState({a: this.state.a + 1}) // a: 'b1' +
ãã®å Žåãå€æŽã¯åå¥ã«ããŒã«ãããããã§ãã
ã»ã¯ã·ã§ã³5. Redux
質å1ã
action, () => {} ? 1) . action type 2) , action type 3) , middleware action 4) , dispatch
åçãšè§£æ3ïŒã¯ãããã®ãããªã¢ã¯ã·ã§ã³ã®ããã«ã«ã¹ã¿ã ããã«ãŠã§ã¢ãå®çŸ©ããå¿
èŠããããŸã
æãåçŽãªäŸãšããŠredux-thunkãåãäžããŠãã ããã ãã¹ãŠã®ããã«ãŠã§ã¢ã¯å°ããªã³ãŒããããã¯ã§ãã
https://github.com/reduxjs/redux-thunk/blob/master/src/index.js#L2-L9
return ({ dispatch, getState }) => next => action => { if (typeof action === 'function') { return action(dispatch, getState, extraArgument); } return next(action); };
ããã«ãŠã§ã¢ã¯ã©ã®ããã«æ©èœããŸããïŒ
ã¢ã¯ã·ã§ã³ãã¹ãã¢ã«å°çããåã«ãã³ã³ãããŒã«ãååŸããŸãã ãããã£ãŠãäžæžããããã¢ã¯ã·ã§ã³ã¯ãæåã«ããã«ãŠã§ã¢ãã§ãŒã³ãééããŸãã
åããã«ãŠã§ã¢ã¯ãã¹ãã¢ã€ã³ã¹ã¿ã³ã¹ã次ã®ã¡ãœãããåãå
¥ããŸããããã«ãããã¢ã¯ã·ã§ã³ãšã¢ã¯ã·ã§ã³èªäœãããã«è»¢éã§ããŸãã
ããã«ãŠã§ã¢ãredux-thunkãªã©ã®ã«ã¹ã¿ã ã¢ã¯ã·ã§ã³ãåŠçããå Žåãã¢ã¯ã·ã§ã³ãé¢æ°ã®å Žåãã¢ã¯ã·ã§ã³ã¯ãã以äžè»¢éããããã "ããã代ããã«ããã«æž¡ãããdispatchããã³getStateã¡ãœããã§ã¢ã¯ã·ã§ã³ãåŒã³åºããŸãã
redux-thunkã次ã«ã¢ã¯ã·ã§ã³ãå®è¡ããå Žåãæ©èœã¯ã©ããªããŸããïŒ
ã¬ãã¥ãŒãµãŒãåŒã³åºãåã«ãstoreã¯ã¢ã¯ã·ã§ã³ã®ã¿ã€ãããã§ãã¯ããŸãã 次ã®æ¡ä»¶ãæºããå¿
èŠããããŸãã
1ïŒãªããžã§ã¯ãã§ãªããã°ãªããŸãã
2ïŒã¿ã€ããã£ãŒã«ããå¿
èŠã§ã
3ïŒåãã£ãŒã«ãã¯æåååã§ãªããã°ãªããŸãã
ããããã®æ¡ä»¶ãæºããããªãå Žåãreduxã¯ãšã©ãŒãã¹ããŒããŸãã
ããŒãã¹ã®è³ªåïŒ
ããŒãã¹è³ªå1ã
? class Todos extends React.Component { getSnapshotBeforeUpdate(prevProps, prevState) { return this.props.list.length - prevProps.list.length; } componentDidUpdate(a, b, c) { console.log(c); } ... } ReactDOM.render(<Todos list={['a','b']} />, app); setTimeout(() => ReactDOM.render(<Todos list={['a','b','a','b']} />, app), 0); a) 0 b) 1 c) 2 d) undefined
åçãšè§£æcïŒ2
getSnapshotBeforeUpdate
ã¯ã getSnapshotBeforeUpdate
ã§ãã£ãã«äœ¿çšãããªãé¢æ°ã§ãããã¹ãããã·ã§ãããååŸããŠããããcomponentDidUpdateã«æž¡ãããšãã§ããŸãã ãã®ã¡ãœããã¯ãç¹å®ã®ããŒã¿ãäºåã«èšç®ããããã«åºã¥ããŠãããšãã°ãã§ãããªã¯ãšã¹ããäœæããããã«å¿
èŠã§ãã
ããŒãã¹è³ªå2ã
2,5 ? function Input() { const [text, setText] = useState("World!"); useEffect( () => { let id = setTimeout(() => { setText("Hello " + text); }, 1000); return () => { clearTimeout(id); }; }, [text] ); return ( <input value={text} onChange={e => { setText(e.target.value); }} /> ); } a) "World!" b) "Hello World!" c) "Hello Hello World!" d)
çãcïŒãHello Hello WorldïŒã
ããã¯ãã§ã«ãreactã®æ°æ©èœãç¥ãããšã®åé¡ã§ãããã¯ã€ãºã«ã¯å«ãŸããŠããŸããã ã³ã¡ã³ããè©ŠããŠãæåŸã®è³ªåã®ã³ãŒãã®åäœã詳现ã«èª¬æããŸããã:)