GMTC 使用 React Hooks 重构 你的小程序

前端狗

2019/07/09 发布于 编程 分类

GMTC2019 

文字内容
1. l k EACR j s
4. c s 0 o @ P ING N >AP :EPT 6IR S - 0VSCHE 3 RA =REAM- y
5. W Wb W W W
7. i r 9 ./ 9 ./ u ./ 9 t s
8. EACR EACR W g W g W2 A ea f React Today and Tomorrow - Dan Abramov, React Conf 2018
9. SE 5SNCRI NA W9I IN A ED 1 8 d Wn g Wx EACR State of Vue - , VueConf CN 2019
10. @HV Mixins ❌ ❌ ❌
11. @HV Mixins HOC ✅ ❌ ✅ ❌ ❌ ❌ ❌
12. @HV Mixins HOC ✅ ❌ ✅ ✅ ❌ ❌ Hooks ❌ ❌ ✅ ✅ ✅
13. >AP Taro 1.3 QQ React Hooks Props Context CLI H5 Taro Doctor JSX
14. b
15. b Hooks React Taro Class state
16. S E=RARE Page({ data: { count:'>count: 0 }, increment () { this.setData({ count:'>count: this.data.count + 1 }) } }) counter.js You clicked {{count}} times !"text>
17. DARA T S E=RARE Page({ data: { count:'>count: 0 }, increment: () !# { this.setData({ count:'>count: this.data.count + 1 }) } }) counter.js ❌ You clicked {{count}} times !"text>
18. S E=RARE function Counter () { const [ count, setCount ] = useState(0) !$ / !$ function increment () { setCount(count + 1) } } return ( You clicked {count} times!"Text>
19. S E=RARE function Counter () { const [ count, setCount ] = useState(0) return ( You clicked {count} times!"Text>
20. S E=RARE function useState (initialState: S (() !# S)) : [S, Dispatch
21. Page({ data: { time:'>time: 60 }, start: false, toggleStart () { this.start = !this.start if (this.start) { this.interval = setInterval(() !# { this.setData({ time:'>time: this.data.time - 1 }) }, 1000) } else { clearInterval(this.interval) } }, onUnload () { clearInterval(this.interval) } }) count-down.js
22. S E4FFECR function Counter () { const [ start, setStart ] = useState(false) const [ time, setTime ] = useState(60) useEffect(() !# { let interval if (start) { interval = setInterval(() !# { setTime(time - 1) }, 1000) } return () !# clearInterval(interval) }, [ start ]) } return (
23. function Counter () { const [ start, setStart ] = useState(false) const [ time, setTime ] = useState(60) useEffect(() !# { !$ effect let interval if (start) { interval = setInterval(() !# { setTime(time - 1) }, 1000) } return () !# clearInterval(interval) }, [ start ]) return (
24. function Counter () { const [ start, setStart ] = useState(false) const [ time, setTime ] = useState(60) useEffect(() !# { !$ effect let interval if (start) { interval = setInterval(() !# { setTime(time - 1) }, 1000) } return () !# clearInterval(interval) }, [ start ]) !$ effect return (
25. function Counter () { const [ start, setStart ] = useState(false) const [ time, setTime ] = useState(60) useEffect(() !# { !$ effect let interval if (start) { interval = setInterval(() !# { setTime(time - 1) }, 1000) } return () !# clearInterval(interval) !$ clean-up }, [ start ]) !$ effect return (
26. function Counter () { const [ start, setStart ] = useState(false) const [ time, setTime ] = useState(60) useEffect(() !# { !$ effect let interval if (start) { interval = setInterval(() !# { setTime(time - 1) !$ ❌ ❌ ❌ }, 1000) } return () !# clearInterval(interval) !$ clean-up }, [ start ]) !$ effect return (
27. function Counter () { const [ start, setStart ] = useState(false) const [ time, setTime ] = useState(60) useEffect(() !# { !$ effect let interval if (start) { interval = setInterval(() !# { setTime(time - 1) !$ ❌ time effect }, 1000) } return () !# clearInterval(interval) !$ clean-up }, [ start ]) !$ effect return (
28. function Counter () { const [ start, setStart ] = useState(false) const [ time, setTime ] = useState(60) useEffect(() !# { !$ effect let interval if (start) { interval = setInterval(() !# { setTime(t !# t - 1) !$ ✅ setTime }, 1000) } return () !# clearInterval(interval) !$ clean-up }, [ start ]) !$ effect return (
29. function Counter () { const [ start, setStart ] = useState(false) const [ time, setTime ] = useState(60) const currentTime = useRef(time) !$ useEffect(() !# { !$ effect let interval if (start) { interval = setInterval(() !# { setTime(currentTime.current!') !$ currentTime.current }, 1000) } return () !# clearInterval(interval) !$ clean-up }, [ start ]) !$ effect } return (
30. function Counter () { const [ start, setStart ] = useState(false) const [ time, setTime ] = useState(60) const interval = useRef() !$ interval useEffect(() !# { !$ effect if (start) { interval.current = setInterval(() !# { setTime(t !# t - 1) !$ ✅ setTime }, 1000) } return () !# clearInterval(interval.current) !$ clean-up }, [ start ]) !$ effect return (
31. g m page.wxml child.wxml You clicked {{count}} times !"text> Click me !"button> !"view> counter.wxml
32. g m bind:increment='>bind:increment="increment" !( !"view> Page({ data: { count:'>count:'>count:'>count:'>count:'>count:'>count:'>count: 0 }, increment () { this.setData({ count:'>count:'>count:'>count:'>count:'>count:'>count:'>count: this.data.count + 1 }) } }) bind:increment='>bind:increment="increment" !( !"view> Component({ properties:'>properties: { count:'>count:'>count:'>count:'>count:'>count:'>count:'>count: Number }, methods:'>methods: { increment () { this.triggerEvent('increment') } } }) You clicked {{count}} times !"text> Click me !"button> !"view> Component({ properties:'>properties: { count:'>count:'>count:'>count:'>count:'>count:'>count:'>count: Number }, methods:'>methods: { increment () { this.triggerEvent('increment') } } })
33. S E2 NRE R export const CounterContext = Taro.createContext(null); const App = () !# { const [ count, setCount ] = useState(0) return ( ); } const Child = () !# ( ); const Counter = () !# { const { count, setCount } = useContext(CounterContext) return ( You clicked {count} times !"Text>
34. S E2 NRE R export const CounterContext = Taro.createContext(null); const App = () !# { const [ count, setCount ] = useState(0) return ( ); } class Child extends Component { shouldComponentUpdate () { return false } } render () { return ( ) } const Counter = () !# { const { count, setCount } = useContext(CounterContext) return ( You clicked {count} times !"Text>
36. !$ function EditableText ({ title }) { const [ editing, setEditing ] = useState(false) } return ( { editing ? {title} !"Text> } !"View> )
37. !$ function EditableText ({ title }) { const [ editing, setEditing ] = useState(false) } return ( { editing ? {title} !"Text> } !"View> ) !)
38. function EditableText ({ title }) { const [ lastClickTime, setClickTime ] = useState(0) const [ editing, setEditing ] = useState(false) return ( { editing ? 0 !* gap < 300) { !$ double click setEditing(true) } setClickTime(currentTime) }} > {title} !"Text> } !"View> ) }
39. function useDoubleClick (cb) { const [ lastClickTime, setClickTime ] = useState(0) } function EditableText ({ title }) { const [ editing, setEditing ] = useState(false) const textOnDoubleClick = useDoubleClick( () !# setEditing(true) ) return (e) !# { const currentTime = e.timeStamp const gap = currentTime - lastClickTime if (gap > 0 !* gap < 300) { cb !* cb(e) } setClickTime(currentTime) } } return ( { editing ? {title} !"Text> } !"View> )
40. function useDoubleClick (cb) { const [ lastClickTime, setClickTime ] = useState(0) } function EditableText ({ title }) { const textOnDoubleClick = useDoubleClick(300, () !# setEditing(true) !$ ❌ setEditing is not defined ) const [ editing, setEditing ] = useState(false) return ( { editing ? {title} !"Text> } !"View> ) return (e) !# { const currentTime = e.timeStamp const gap = currentTime - lastClickTime if (gap > 0 !* gap < 300) { cb !* cb(e) } setClickTime(currentTime) } }
41. function EditableText ({ title }) { const [ editing, setEditing ] = useState(false) const textOnDoubleClick = useDoubleClick(300) function useDoubleClick (cb) { const [ lastClickTime, setClickTime ] = useState(0) } return ( { editing ? {title} !"Text> } !"View> ) return (e) !# { const currentTime = e.timeStamp const gap = currentTime - lastClickTime if (gap > 0 !* gap < 300) { cb !* cb(e) } setClickTime(currentTime) } }
42. function EditableText ({ title }) { const [ editing, setEditing ] = useState(false) const textOnDoubleClick = useDoubleClick() function useDoubleClick () { const [ lastClickTime, setClickTime ] = useState(0) } return (callback) !# (e) !# { const currentTime = e.timeStamp const gap = currentTime - lastClickTime if (gap > 0 !* gap < 300) { callback !* callback(e) } setClickTime(currentTime) } } return ( { editing ? {title} !"Text> } !"View> )
43. function EditableText ({ title }) { const textOnDoubleClick = useDoubleClick() const buttonOnDoubleClick = useDoubleClick() !$ } return ( {title} !"Text>
44. hv class Numbers extends Component { shouldComponentUpdate () { return false } render () { return { expensive(this.props.array) .map(i !# {i}!"View>) } !"View> } }
45. hv class Numbers extends Component { shouldComponentUpdate () { return false } render () { return { expensive(this.props.array) .map(i !# {i}!"View>) } !"View> } } function Numbers ({ array }) { return ( { expensive(array).map( i !# {i}!"View> ) } !"View> ) } export default Taro.memo(Numbers, () !# true)
46. hv function Counter () { const [ count, setCount ] = useState(0) const [val, setValue] = useState('') function expensive() { let sum = 0 for (let i = 0; i < count * 1e9; i!,) { sum += i } return sum } } return ( You clicked {expensive()} times}!"Text>
47. hv function Counter () { const [ count, setCount ] = useState(0) const [val, setValue] = useState('') function expensive() { let sum = 0 for (let i = 0; i < count * 1e9; i!,) { sum += i } return sum } } function Counter () { const [ count, setCount ] = useState(0) const [val, setValue] = useState('') const expensive = useMemo(() !# { let sum = 0 for (let i = 0; i < count * 100; i!,) { sum += i } return sum }, [count]) !$ ✅ count return ( You clicked {expensive()} times}!"Text>
48. hv memo !" memoization memoization
49. React Redux useSelector() useDispatch() useStore() react-redux@7 useState() react-redux.js.org/next/api/hooks useContext() useEffect() useMemo() connect()
52.
53. Hooks
54. • • Hooks React • React Hooks • Hooks
55. const CurrentOwner: { current:'>current: null Component, index:'>index: number } = { !$ Taro , !$ current:'>current: null, !$ Taro hooks !$ Hook index:'>index: 0 }
56. const CurrentOwner: { current:'>current: null Component, index:'>index: number } = { !$ Taro , !$ current:'>current: null, !$ Taro hooks !$ Hook index:'>index: 0 } React.!-SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner
57. function getHook (): Hook { if (CurrentOwner.current !!/ null) { throw new Error(`invalid hooks call: hooks can only be called in a taro component.`) } const index = CurrentOwner.index!, !$ hook Taro ID const hooks: Hook[] = CurrentOwner.current.hooks !$ hooks if (index !0 hooks.length) { !$ hook hooks.push({} as Hook) !$ hook } return hooks[index] !$ hook }
58. function useState (initialState: S (() !# S)): [S, Dispatch !$ hook if (isUndefined(hook.state)) { !$ hook hook.component = Current.current! !$ Taro hook.state = [ !$ hook.state initialState, (action) !# { hook.state[0] = isFunction(action) ? action(hook.state[0]) : action enqueueRender(hook.component) !$ } ] } return hook.state !$ hook }
60. React create-react-app eslint-plugin-hooks prepack prettier
61. C Taro esling-plugin-taro Taro Doctor Taro Taro
65. THANKS THANKS! THANKS!