React를 배우고 사용할 때 숙지해야 할 JavaScript 기능
내가 사용한 다른 프레임워크와 비교하여 React에서 가장 좋아하는 것 중 하나는 JavaScript를 사용할 때 노출되는 방식입니다. 템플릿 DSL (JSX는 현명한 JavaScript로 컴파일)이 없으며 구성 요소 API는 React Hooks를 추가하여 더욱 간단 해졌으며 프레임 워크는 핵심 UI 외부에서 해결하려는 추상화를 거의 제공하지 않습니다.
https://kentcdodds.com/blog/javascript-to-know-for-react
이 때문에 JavaScript 기능을 배우는 것이 React로 응용 프로그램을 효과적으로 구축하는 것이 좋습니다. 여기에 React 작업을 최대한 효과적으로 수행 할 수 있도록 학습에 시간을 할애하는 것이 좋습니다.
템플릿 리터럴
템플릿 리터럴은 초강력을 가진 일반 문자열과 같습니다.
const greeting = 'Hello'
2const subject = 'World'
3console.log(`${greeting} ${subject}!`)
4
5
6console.log(greeting + ' ' + subject + '!')
7
8
9function Box({className, ...props}) {
10 return <div className={`box ${className}`} {...props} />
11}
MDN: Template Literals
속기 속성 이름(Shorthand property names)
이것은 매우 일반적이며 유용하므로 지금은 생각하지 않아도 됩니다.
const a = 'hello'
2const b = 42
3const c = {d: [true, false]}
4console.log({a, b, c})
5
6
7console.log({a: a, b: b, c: c})
8
9
10function Counter({initialCount, step}) {
11 const [count, setCount] = useCounter({initialCount, step})
12 return <button onClick={setCount}>{count}</button>
13}
MDN: Object initializer New notations in ECMAScript 2015
화살표 함수 (Arrow functions)
화살표 함수는 JavaScript에서 함수를 작성하는 또 다른 방법이지만 의미상 몇 가지 차이점이 있습니다. 운 좋게도 React land에서는 클래스가 아닌 프로젝트에서 후크를 사용하는 경우 이 문제에 대해 걱정할 필요가 없지만 화살표 함수를 사용하면 익명의 함수와 암시적인 반환이 더 가능합니다. 화살표 함수를 충분히 사용하고 싶습니다.
const getFive = () => 5
2const addFive = a => a + 5
3const divide = (a, b) => a / b
4
5
6function getFive() {
7 return 5
8}
9function addFive(a) {
10 return a + 5
11}
12function divide(a, b) {
13 return a / b
14}
15
16
17function TeddyBearList({teddyBears}) {
18 return (
19 <ul>
20 {teddyBears.map(teddyBear => (
21 <li key={teddyBear.id}>
22 <span>{teddyBear.name}</span>
23 </li>
24 ))}
25 </ul>
26 )
27}
위의 예에서 주목할 점은 여는 괄호와 닫는 괄호입니다. 이는 JSX로 작업 할 때 화살표 함수의 암시 적 반환 기능을 활용하는 일반적인 방법입니다.
MDN: Arrow Functions
파괴(Destructuring)
파괴는 아마도 내가 가장 좋아하는 JavaScript 기능 일 것입니다. 객체와 배열을 항상 구조화합니다 (useState를 사용하는 경우에도 마찬가지입니다). 나는 그것이 얼마나 선언적 인지를 좋아합니다.
2
3
4function makeCalculation({x, y: d, z = 4}) {
5 return Math.floor((x + d + z) / 3)
6}
7
8
9function makeCalculation(obj) {
10 const {x, y: d, z = 4} = obj
11 return Math.floor((x + d + z) / 3)
12}
13
14
15function makeCalculation(obj) {
16 const x = obj.x
17 const d = obj.y
18 const z = obj.z === undefined ? 4 : obj.z
19 return Math.floor((x + d + z) / 3)
20}
21
22
23function UserGitHubImg({username = 'ghost', ...props}) {
24 return <img src={`https://github.com/${username}.png`} {...props} />
25}
MDN: Destructuring assignment
그 MDN 기사를 확실히 읽으십시오. 새로운 것을 배워야 합니다. 완료되면 한 줄의 파괴를 사용하도록 이것을 리팩토링 하십시오.
function nestedArrayAndObject() {
2
3 const info = {
4 title: 'Once Upon a Time',
5 protagonist: {
6 name: 'Emma Swan',
7 enemies: [
8 {name: 'Regina Mills', title: 'Evil Queen'},
9 {name: 'Cora Mills', title: 'Queen of Hearts'},
10 {name: 'Peter Pan', title: `The boy who wouldn't grow up`},
11 {name: 'Zelena', title: 'The Wicked Witch'},
12 ],
13 },
14 }
15
16 const title = info.title
17 const protagonistName = info.protagonist.name
18 const enemy = info.protagonist.enemies[3]
19 const enemyTitle = enemy.title
20 const enemyName = enemy.name
21 return `${enemyName} (${enemyTitle}) is an enemy to ${protagonistName} in "${title}"`
22}
매개 변수 기본값 (Parameter defaults)
이것은 내가 항상 사용하는 또 다른 기능입니다. 함수의 기본 값을 선언적으로 표현하는 정말 강력한 방법입니다.
2
3function add(a, b = 0) {
4 return a + b
5}
6
7
8const add = (a, b = 0) => a + b
9
10
11function add(a, b) {
12 b = b === undefined ? 0 : b
13 return a + b
14}
15
16
17function useLocalStorageState({
18 key,
19 initialValue,
20 serialize = v => v,
21 deserialize = v => v,
22}) {
23 const [state, setState] = React.useState(
24 () => deserialize(window.localStorage.getItem(key)) || initialValue,
25 )
26
27 const serializedState = serialize(state)
28 React.useEffect(() => {
29 window.localStorage.setItem(key, serializedState)
30 }, [key, serializedState])
31
32 return [state, setState]
33}
MDN: Default parameters
Rest/Spread
... 구문은 값 모음에서 작동하는 일종의 "컬렉션"구문으로 생각할 수 있습니다. 나는 항상 그것을 사용하고 그것을 어떻게 그리고 어떻게 사용할 수 있는지 배우는 것이 좋습니다. 실제로는 상황에 따라 다른 의미가 있으므로 뉘앙스를 배우면 도움이 될 것입니다.
const arr = [5, 6, 8, 4, 9]
2Math.max(...arr)
3
4Math.max.apply(null, arr)
5
6const obj1 = {
7 a: 'a from obj1',
8 b: 'b from obj1',
9 c: 'c from obj1',
10 d: {
11 e: 'e from obj1',
12 f: 'f from obj1',
13 },
14}
15const obj2 = {
16 b: 'b from obj2',
17 c: 'c from obj2',
18 d: {
19 g: 'g from obj2',
20 h: 'g from obj2',
21 },
22}
23console.log({...obj1, ...obj2})
24
25console.log(Object.assign({}, obj1, obj2))
26
27function add(first, ...rest) {
28 return rest.reduce((sum, next) => sum + next, first)
29}
30
31function add() {
32 const first = arguments[0]
33 const rest = Array.from(arguments).slice(1)
34 return rest.reduce((sum, next) => sum + next, first)
35}
36
37
38function Box({className, ...restOfTheProps}) {
39 const defaultProps = {
40 className: `box ${className}`,
41 children: 'Empty box',
42 }
43 return <div {...defaultProps} {...restOfTheProps} />
44}
MDN: Spread syntax
MDN: Rest parameters
ESModules
최신 도구를 사용하여 앱을 빌드 하는 경우 모듈을 지원할 가능성이 높습니다. 사소한 크기의 애플리케이션이라도 코드 재사용 및 구성에 모듈을 사용해야 할 수 있으므로 구문이 작동하는 방식을 배우는 것이 좋습니다.
export default function add(a, b) {
2 return a + b
3}
4
5
6
7
8
9
10export const foo = 'bar'
11
12
13
14
15
16
17export function subtract(a, b) {
18 return a - b
19}
20
21export const now = new Date()
22
23
24
25
26
27
28
29
30import React, {Suspense, Fragment} from 'react'
MDN: import
MDN: export
또 다른 자료로서, 나는 이 문법에 대해 전체적으로 이야기했고 여기서 그 이야기를 볼 수 있습니다.
Ternaries
나는 삼항을 좋아합니다. 그들은 아름답게 선언적입니다. 특히 JSX에서.
const message = bottle.fullOfSoda
2 ? 'The bottle has soda!'
3 : 'The bottle may not have soda :-('
4
5
6let message
7if (bottle.fullOfSoda) {
8 message = 'The bottle has soda!'
9} else {
10 message = 'The bottle may not have soda :-('
11}
12
13
14function TeddyBearList({teddyBears}) {
15 return (
16 <React.Fragment>
17 {teddyBears.length ? (
18 <ul>
19 {teddyBears.map(teddyBear => (
20 <li key={teddyBear.id}>
21 <span>{teddyBear.name}</span>
22 </li>
23 ))}
24 </ul>
25 ) : (
26 <div>There are no teddy bears. The sadness.</div>
27 )}
28 </React.Fragment>
29 )
30}
MDN: Conditional (ternary) operator
Array Methods
배열은 환상적이며 항상 배열 방법을 사용합니다! 아마도 다음 방법을 가장 자주 사용합니다.
- find
- some
- every
- includes
- map
- filter
- reduce
여기 예시들이 있습니다 :
const dogs = [
2 {
3 id: 'dog-1',
4 name: 'Poodle',
5 temperament: [
6 'Intelligent',
7 'Active',
8 'Alert',
9 'Faithful',
10 'Trainable',
11 'Instinctual',
12 ],
13 },
14 {
15 id: 'dog-2',
16 name: 'Bernese Mountain Dog',
17 temperament: ['Affectionate', 'Intelligent', 'Loyal', 'Faithful'],
18 },
19 {
20 id: 'dog-3',
21 name: 'Labrador Retriever',
22 temperament: [
23 'Intelligent',
24 'Even Tempered',
25 'Kind',
26 'Agile',
27 'Outgoing',
28 'Trusting',
29 'Gentle',
30 ],
31 },
32]
33
34dogs.find(dog => dog.name === 'Bernese Mountain Dog')
35
36
37dogs.some(dog => dog.temperament.includes('Aggressive'))
38
39
40dogs.some(dog => dog.temperament.includes('Trusting'))
41
42
43dogs.every(dog => dog.temperament.includes('Trusting'))
44
45
46dogs.every(dog => dog.temperament.includes('Intelligent'))
47
48
49dogs.map(dog => dog.name)
50
51
52dogs.filter(dog => dog.temperament.includes('Faithful'))
53
54
55dogs.reduce((allTemperaments, dog) => {
56 return [...allTemperaments, ...dog.temperaments]
57}, [])
58
59
60
61function RepositoryList({repositories, owner}) {
62 return (
63 <ul>
64 {repositories
65 .filter(repo => repo.owner === owner)
66 .map(repo => (
67 <li key={repo.id}>{repo.name}</li>
68 ))}
69 </ul>
70 )
71}
MDN: Array
Promises and async/await
이것은 큰 주제이며 그들과 잘 지내려면 약간의 연습과 시간이 걸릴 수 있습니다. Promises은 JavaScript 생태계의 어느 곳에서나 가능하며, React가 해당 생태계에 얼마나 강력한 지 덕분에 어느 곳에 나 있습니다 (사실, React 자체는 promises을 내부적으로 사용함).
약Promises은 비동기 코드를 관리하는 데 도움이 되며 타사 라이브러리 뿐만 아니라 많은 DOM API에서 반환 됩니다. Async/await 구문은 promises을 처리하기 위한 특수 구문입니다. 두 개가 함께 갑니다.
function promises() {
2 const successfulPromise = timeout(100).then(result => `success: ${result}`)
3
4 const failingPromise = timeout(200, true).then(null, error =>
5 Promise.reject(`failure: ${error}`),
6 )
7
8 const recoveredPromise = timeout(300, true).then(null, error =>
9 Promise.resolve(`failed and recovered: ${error}`),
10 )
11
12 successfulPromise.then(log, logError)
13 failingPromise.then(log, logError)
14 recoveredPromise.then(log, logError)
15}
16
17function asyncAwaits() {
18 async function successfulAsyncAwait() {
19 const result = await timeout(100)
20 return `success: ${result}`
21 }
22
23 async function failedAsyncAwait() {
24 const result = await timeout(200, true)
25 return `failed: ${result}`
26 }
27
28 async function recoveredAsyncAwait() {
29 let result
30 try {
31 result = await timeout(300, true)
32 return `failed: ${result}`
33 } catch (error) {
34 return `failed and recovered: ${error}`
35 }
36 }
37
38 successfulAsyncAwait().then(log, logError)
39 failedAsyncAwait().then(log, logError)
40 recoveredAsyncAwait().then(log, logError)
41}
42
43function log(...args) {
44 console.log(...args)
45}
46
47function logError(...args) {
48 console.error(...args)
49}
50
51
52function timeout(duration = 0, shouldReject = false) {
53 return new Promise((resolve, reject) => {
54 setTimeout(() => {
55 if (shouldReject) {
56 reject(`rejected after ${duration}ms`)
57 } else {
58 resolve(`resolved after ${duration}ms`)
59 }
60 }, duration)
61 })
62}
63
64
65function GetGreetingForSubject({subject}) {
66 const [isLoading, setIsLoading] = React.useState(false)
67 const [error, setError] = React.useState(null)
68 const [greeting, setGreeting] = React.useState(null)
69
70 React.useEffect(() => {
71 async function fetchGreeting() {
72 try {
73 const response = await window.fetch('https://example.com/api/greeting')
74 const data = await response.json()
75 setGreeting(data.greeting)
76 } catch (error) {
77 setError(error)
78 } finally {
79 setIsLoading(false)
80 }
81 }
82 setIsLoading(true)
83 fetchGreeting()
84 }, [])
85
86 return isLoading ? (
87 'loading...'
88 ) : error ? (
89 'ERROR!'
90 ) : greeting ? (
91 <div>
92 {greeting} {subject}
93 </div>
94 ) : null
95}
MDN: Promise
MDN: async function
MDN: await
결론
물론 React 앱을 빌드 할 때 유용한 많은 언어 기능이 있지만 이것들은 내가 자주 사용하는 것을 좋아하는 것들 중 일부입니다. 이 정보가 도움이 되길 바랍니다.