Upgrade to Pro — share decks privately, control downloads, hide ads and more …

React Hooks + TS + functional = 아름다움

React Hooks + TS + functional = 아름다움

JS 기반의 class component로 구성된 프로젝트를 ts + hoos 기반의 functional component 프로젝트로 변환하면서 느낀 것, 그것은 미니멀리즘의 아름다움이었습니다.

https://alice.finance

Yoonjae Yoo

June 22, 2019
Tweet

More Decks by Yoonjae Yoo

Other Decks in Programming

Transcript

  1. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere ALICE - ఎ઺ঔചػ Әਲ਼ জ 3 Picture Place Holder Picture Place Holder ୊਺ࠗఠ ௼۽झ ೒ۖಬਸ ৏ف೧فҊ ѐߊ. REACT NATIVE ѐੋఃܳ ૒੽ ҙܻೞݴ ੉؊ܻ਑ ࠶۾୓ੋҗ ాन. ੉؊ܻ਑ ӝ߈੄ DAPP 2019֙ 6ਘ ੷୷ ࢲ࠺झ য়೑, 2019֙ 7ਘ ׸ࠁ؀୹ য়೑ ৘੿ ঐഐചತ ੷୷/׸ࠁ؀୹ ࢲ࠺झ 01 02 03
  2. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere ALICE MVP: 2019/04 4 Flowա TypeScriptܳ ࢎਊೞ૑ ঋ਺. ECMA2015 ۽૒ਸ ੤ࢎਊೡ ٸ ઱۽ HOCਸ ࢎਊ. HIGHER-ORDER COMPONENTS React 16.5, ௿ېझ ஹನք౟ ӝ߈. CLASS COMPONENTS
  3. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere ALICE 1.0: 2019/06 5 React 16.8, ௿ېझ ஹನք౟ ӝ߈. FUNCTIONAL COMPONENTS ௏٘੄ ੤ࢎਊࢿਸ ֫ৈષ. REACT HOOKS ஹ౵ੌ ఋ੐ ఋੑ ୓௼. TYPESCRIPT
  4. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere OLD SOURCE CODE 7 class MyComponent extends React.Component { state = { count: 0 }; componentDidMount() { alert(this.props.name); } render() { return ( <View> <Button onPress={this.onPress}> <Text>Count: {this.state.count}</Text> </Button> </View> ); } onPress = () => this.setState({ count: this.state.count + 1 }); } export default MyComponent; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
  5. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere OLD SOURCE CODE: RENDER 8 class MyComponent extends React.Component { state = { count: 0 }; componentDidMount() { alert(this.props.name); } render() { return ( <View> <Button onPress={this.onPress}> <Text>Count: {this.state.count}</Text> </Button> </View> ); } onPress = () => this.setState({ count: this.state.count + 1 }); } export default MyComponent; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
  6. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere NEW SOURCE CODE: RENDER 9 const MyComponent = ({ name }) => { return ( <View> <Button onPress={{/*this.onPress*/}}> <Text>Count: {{/*this.state.count*/}}</Text> </Button> </View> ); }; export default MyComponent; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
  7. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere FUNCTIONAL COMPONENTS: TIPS 10 const MyComponent = ({ name }) => ( <View> <Button onPress={{/*this.onPress*/}}> <Text>Count: {{/*this.state.count*/}}</Text> </Button> </View> ); export default MyComponent; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 return ఃਕ٘ܳ ࢤۚೞҊ ؊਌ рѾ ೞѱ ੘ࢿೡ ࣻب ੓׮.
  8. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere FUNCTIONAL COMPONENTS: WARNINGS 11 const MyComponent = ({ name }) => { const value = intenseCalculation(); return ( <View> <Button onPress={{/*this.onPress*/}}> <Text>Count: {{/*this.state.count*/}}</Text> </Button> </View> ); }; export default MyComponent; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ೣࣻ ղ੄ ۽૒਷ ۪؊݂੉ ࣻ೯ؼ ٸ ݃׮ ݒߣ ҅࢑ػ׮.
  9. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere FUNCTIONAL COMPONENTS: WARNINGS 12 const MyComponent = ({ name }) => { const onPress = () => { // handle press }; return ( <View> <Button onPress={onPress}> <Text>Count: {{/*this.state.count*/}}</Text> </Button> </View> ); }; export default MyComponent; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ೣࣻ ղীࢲ ࢜۽਍ ೣࣻܳ ٜ݅ݶ ؊ ؊਌ য়ߡ೻٘о ௼׮.
  10. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere FUNCTIONAL COMPONENTS: ERRORS 13 const MyComponent = () => { const { name } = this.props; // undefined error return ( <View> <Button onPress={onPress}> <Text>Count: {{/*this.state.count*/}}</Text> </Button> </View> ); }; export default MyComponent; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ೣࣻഋ ஹನք౟ীࢲח this.props ਸ оઉৢ ࣻ হ׮.
  11. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere OLD SOURCE CODE: STATE 15 class MyComponent extends React.Component { state = { count: 0 }; componentDidMount() { alert(this.props.name); } render() { return ( <View> <Button onPress={this.onPress}> <Text>Count: {this.state.count}</Text> </Button> </View> ); } onPress = () => this.setState({ count: this.state.count + 1 }); } export default MyComponent; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
  12. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere NEW SOURCE CODE: STATE 16 const MyComponent = ({ name }) => { const [count, setCount] = useState(0); return ( <View> <Button onPress={{/*this.onPress*/}}> <Text>Count: {count}</Text> </Button> </View> ); }; export default MyComponent; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 useState()ח ୡӝчਸ ੋ੗۽ ߉Ҋ getter৬ setterܳ ׸਷ ߓৌਸ ܻఢ
  13. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere USESTATE: TIPS 17 const MyComponent = ({ name }) => { const [count, setCount] = useState(() => intenseCalculation()); return ( <View> <Button onPress={{/*this.onPress*/}}> <Text>Count: {count}</Text> </Button> </View> ); }; export default MyComponent; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 useState੄ ࢤࢿ੗ী ೣࣻܳ ੹׳ೞ ݶ ୭ୡ ೠߣ݅ ো࢑੉ ࣻ೯ػ׮.
  14. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere USESTATE: TIPS 18 const MyComponent = ({ name }) => { const [count, setCount] = useState([{ num: 0 }]); return ( <View> <Button onPress={{/*this.onPress*/}}> <Text>Count: {count}</Text> </Button> </View> ); }; export default MyComponent; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 state੄ ؀࢚੉ غח ч਷ string, number, boolean ࡺ݅ ইפۄ array, object۽ ҳࢿػ যځೠ ч੉ যب ࢚ҙহ׮.
  15. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere USESTATE: ERRORS 19 const MyComponent = ({ name }) => { const init = () => { const [count, setCount] = useState(0); }; // error return ( <View> <Button onPress={{/*this.onPress*/}}> <Text>Count: {count}</Text> </Button> </View> ); }; export default MyComponent; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ݽٚ hook਷ ೣࣻ੄ ୭࢚ਤ ۨ߰ী ࢲ ഐ୹غযঠ ೞ޲۽ ೣࣻ উীࢲ ഐ ୹ؼ ࣻ হ׮.
  16. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere USESTATE: ERRORS 20 const MyComponent = ({ name }) => { if (name) { const [count, setCount] = useState(0); } // error return ( <View> <Button onPress={{/*this.onPress*/}}> <Text>Count: {count}</Text> </Button> </View> ); }; export default MyComponent; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ݽٚ hook਷ ೣࣻ੄ ୭࢚ਤ ۨ߰ী ࢲ ഐ୹غযঠ ೞ޲۽ ઑѤޙ উীࢲ ഐ୹ؼ ࣻ হ׮.
  17. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere 21 React Hooks useCallback
  18. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere OLD SOURCE CODE: CALLBACK 22 class MyComponent extends React.Component { state = { count: 0 }; componentDidMount() { alert(this.props.name); } render() { return ( <View> <Button onPress={this.onPress}> <Text>Count: {this.state.count}</Text> </Button> </View> ); } onPress = () => this.setState({ count: this.state.count + 1 }); } export default MyComponent; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
  19. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere NEW SOURCE CODE: CALLBACK 23 const MyComponent = ({ name }) => { const [count, setCount] = useState(0); const onPress = useCallback(() => setCount(count + 1), [count]); return ( <View> <Button onPress={onPress}> <Text>Count: {count}</Text> </Button> </View> ); }; export default MyComponent; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 useCallback()ח ഐ୹ؼ ೣࣻ, ੤҅ ࢑ਸ ਤೠ ੄ઓࢿ ݾ۾ਸ ੋ੗۽ ߉ח ׮.
  20. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere USECALLBACK : TIPS 24 const MyComponent = ({ name }) => { const [count, setCount] = useState(0); const onPress = useCallback(async () => { await funcAsync(); }, []); return ( <View> <Button onPress={onPress}> <Text>Count: {count}</Text> </Button> </View> ); }; export default MyComponent; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 async ೣࣻب ૑ਗ੉ ػ׮.
  21. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere USECALLBACK : WARNING 25 const MyComponent = ({ name }) => { const [count, setCount] = useState(0); const onPress = useCallback(() => setCount(count + 1), [count]); // setCount always called with count == 0 return ( <View> <Button onPress={onPress}> <Text>Count: {count}</Text> </Button> </View> ); }; export default MyComponent; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 useCallback()੄ فߣ૩ ੋ੗ী ࠼ ߓৌਸ ੹׳ೞݶ ௒ߔ ೣࣻח ୭ୡ ࢚ క۽ Ҋ੿غҊ ੉റী ੤҅࢑غ૑ ঋ ח׮.
  22. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere 26 React Hooks useEffect
  23. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere OLD SOURCE CODE: EFFECT 27 class MyComponent extends React.Component { state = { count: 0 }; componentDidMount() { alert(this.props.name); } render() { return ( <View> <Button onPress={this.onPress}> <Text>Count: {this.state.count}</Text> </Button> </View> ); } onPress = () => this.setState({ count: this.state.count + 1 }); } export default MyComponent; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
  24. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere NEW SOURCE CODE: EFFECT 28 const MyComponent = ({ name }) => { const [count, setCount] = useState(0); const onPress = useCallback(() => setCount(count + 1), [count]); useEffect(() => { alert(name); }, []); return ( <View> <Button onPress={onPress}> <Text>Count: {count}</Text> </Button> </View> ); }; export default MyComponent; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 useEffect()ח ഐ୹ؼ ೣࣻ, ੤҅࢑ ਸ ਤೠ ੄ઓࢿ ݾ۾ਸ ੋ੗۽ ߉ח ׮. ೣࣻח ۪؊݂੉ ৮ܐػ റী ࣻ ೯ػ׮.
  25. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere USEEFFECT - TIPS 29 const MyComponent = ({ name }) => { const [count, setCount] = useState(0); const onPress = useCallback(() => setCount(count + 1), [count]); useEffect(() => { alert(name); return () => { alert("clean-up") }; }, []); return ( <View> <Button onPress={onPress}> <Text>Count: {count}</Text> </Button> </View> ); }; export default MyComponent; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 useEffectীࢲ ੿ܻ(clean-up) ೣࣻ ܳ ܻఢೡ ࣻ ੓׮. ੉ ח ௿ ې झ ஹ ನ ք ౟ ੄ componentWillUnmount() ী ೧ ׼ೠ׮.
  26. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere USEEFFECT - TIPS 30 const MyComponent = ({ name }) => { const [count, setCount] = useState(0); const onPress = useCallback(() => setCount(count + 1), [count]); useEffect(() => { alert(name); }, [name]); return ( <View> <Button onPress={onPress}> <Text>Count: {count}</Text> </Button> </View> ); }; export default MyComponent; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 useEffectীࢲ ੹׳ೞח فߣ૩ ੋ ੗੄ чٜ੉ ߸҃ؼ ٸ݃׮ ೣࣻо ࣻ ೯ ػ ׮ . ( ৘ ઁ ী ࢲ ח n a m e property੄ ч੉ ߸҃ؼ ٸ݃׮ ೣ ࣻо ഐ୹ػ׮.) ੉ ח ௿ ې झ ஹ ನ ք ౟ ੄ componentDidUpdate() ী ೧׼ ೠ׮.
  27. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere USEEFFECT - WARNINGS 31 const MyComponent = ({ name }) => { const [count, setCount] = useState(0); const onPress = useCallback(() => setCount(count + 1), [count]); useEffect(() => { alert(name); }); // called every frame return ( <View> <Button onPress={onPress}> <Text>Count: {count}</Text> </Button> </View> ); }; export default MyComponent; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 useEffect੄ فߣ૩ ੋ੗ח ੹׳ೞ ૑ ঋইب غ૑݅ Ӓۡ ҃਋ ೣࣻח ۪؊݂੉ ࣻ೯غח ೐ۨ੐݃׮ ഐ୹ ػ׮. (ಌನݢझ ੉ग)
  28. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere USEEFFECT - ERRORS 32 const MyComponent = ({ name }) => { const [count, setCount] = useState(0); const onPress = useCallback(() => setCount(count + 1), [count]); useEffect(async () => { await funcAsync(); }, []); // error return ( <View> <Button onPress={onPress}> <Text>Count: {count}</Text> </Button> </View> ); }; export default MyComponent; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 useEffectীח async ೣࣻܳ ੹׳ ೡ ࣻ হ׮.
  29. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere 33 React Hooks Custom Hook
  30. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere OLD SOURCE CODE 34 const MyComponent = ({ name }) => { const [count, setCount] = useState(0); const onPress = useCallback(() => setCount(count + 1), [count]); useEffect(() => { alert(name); }, []); return ( <View> <Button onPress={onPress}> <Text>Count: {count}</Text> </Button> </View> ); }; export default MyComponent; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
  31. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere NEW SOURCE CODE 35 const MyComponent = ({ name }) => { const { count, onPress } = useIncrementer(name); return ( <View> <Button onPress={onPress}> <Text>Count: {count}</Text> </Button> </View> ); }; const useIncrementer = (name: string) => { const [count, setCount] = useState(0); const onPress = useCallback(() => setCount(count + 1), [count]); useEffect(() => { alert(name); }, []); return { count, onPress }; }; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ৈ۞о૑ ۽૒ਸ ޘযࢲ ழझథ ലਸ ٜ݅ ࣻ ੓׮. ௿ېझ ஹನք౟۽ח ҳഅೡ ࣻ হח ೣࣻഋ ஹನք౟݅੄ ੢੼੉׮.
  32. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere OLD SOURCE CODE 37 class MyComponent extends React.Component { render() { return ( <View> <Text>Name: {this.props.name}</Text> <Text>Age: {this.props.age}</Text> <Text>Female: {this.props.female}</Text> </View> ); } } MyComponent.propTypes = { name: PropTypes.string, age: PropTypes.number, female: PropTypes.bool }; export default MyComponent; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
  33. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere NEW SOURCE CODE: PROPS 38 interface MyComponentProps { name?: string; age?: number; female?: boolean; } const MyComponent = ({ name, age, female }: MyComponentProps) => { return ( <View> <Text>Name: {name}</Text> <Text>Age: {age}</Text> <Text>Female: {female}</Text> </View> ); }; export default MyComponent; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
  34. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere NEW SOURCE CODE: PROPS 39 interface MyComponentProps { name?: string; age?: number; female?: boolean; } const MyComponent: React.FunctionComponent<MyComponentProps> = ({ name, age, female }) => { return ( <View> <Text>Name: {name}</Text> <Text>Age: {age}</Text> <Text>Female: {female}</Text> </View> ); }; export default MyComponent; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 / / ੉੹ ੢җ زੌೠ ௏٘
  35. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere TYPESCRIPT: STATES 40 const [count, setCount] = useState(0); // count੄ ఋੑ਷ number݅ оמ const [count, setCount] = useState<number>(0); // ਤ৬ زੌ const [count, setCount] = useState<number | null>(0); // count੄ ఋੑ਷ number ഑਷ null੉ оמ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
  36. React Hooks + TS + Functional = ইܴ׮਑ JavaScript Is

    Everywhere TYPESCRIPT: CALLBACK 41 const onPress = useCallback((text) => alert(text), [text]); // text੄ ఋੑ਷ any const onPress = useCallback((text: string) => alert(text), [text]); // text੄ ఋੑ਷ string 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20