Author: Kent C. Dodds
Translator: Crazy Technology House
Original: https://kentcdodds.com/blog/j...
Reproduction is strictly prohibited without permission
One of the reasons I like React best than the other frameworks I use is its exposure to JavaScript. Without a template DSL (JSX compiled into reasonable JavaScript), component API s are simply added React Hooks It becomes simpler, and the framework provides very few abstractions for solving core UI problems.
Therefore, learning JavaScript is highly desirable for effective application building using React. So here are some JavaScript features, and I recommend that you spend some time studying so that you can use React as effectively as possible.
Template text
Template text is like a super-capable string:
const greeting = 'Hello' const subject = 'World' console.log(`${greeting} ${subject}!`) // Hello World! // this is the same as: console.log(greeting + ' ' + subject + '!') // in React: function Box({className, ...props}) { return <div className={`box ${className}`} {...props} /> }
Short Attribute Name
It's very common and useful, and I haven't thought I could do that until now.
const a = 'hello' const b = 42 const c = {d: [true, false]} console.log({a, b, c}) // this is the same as: console.log({a: a, b: b, c: c}) // in React: function Counter({initialCount, step}) { const [count, setCount] = useCounter({initialCount, step}) return <button onClick={setCount}>{count}</button> }
MDN: A New Representation of Object Initialization in ECMAScript 2015
Arrow function
Arrow functions are another way to write functions in JavaScript, but they do have some semantic differences. Fortunately, we don't have to worry about this if we use hook s (not classes) on React's land, but arrow functions allow more complex anonymous functions and implicit returns, so you'll see and want to make full use of arrow functions.
const getFive = () => 5 const addFive = a => a + 5 const divide = (a, b) => a / b // this is the same as: function getFive() { return 5 } function addFive(a) { return a + 5 } function divide(a, b) { return a / b } // in React: function TeddyBearList({teddyBears}) { return ( <ul> {teddyBears.map(teddyBear => ( <li key={teddyBear.id}> <span>{teddyBear.name}</span> </li> ))} </ul> ) }
deconstruction
Deconstruction is probably my favorite JavaScript feature. I've been building objects and arrays (if you use useState, maybe so, Like this ) I like its declarative nature.
// const obj = {x: 3.6, y: 7.8} // makeCalculation(obj) function makeCalculation({x, y: d, z = 4}) { return Math.floor((x + d + z) / 3) } / this is the same as function makeCalculation(obj) { const {x, y: d, z = 4} = obj return Math.floor((x + d + z) / 3) } // which is the same as function makeCalculation(obj) { const x = obj.x const d = obj.y const z = obj.z === undefined ? 4 : obj.z return Math.floor((x + d + z) / 3) } // in React: function UserGitHubImg({username = 'ghost', ...props}) { return <img src={`https://github.com/${username}.png`} {...props} /> }
MDN: Deconstructive Distribution
Once you read the MDN articles, you will surely be able to learn something new. When you're done, try to deconstruct in a single line:
function nestedArrayAndObject() { // refactor this to a single line of destructuring... const info = { title: 'Once Upon a Time', protagonist: { name: 'Emma Swan', enemies: [ {name: 'Regina Mills', title: 'Evil Queen'}, {name: 'Cora Mills', title: 'Queen of Hearts'}, {name: 'Peter Pan', title: `The boy who wouldn't grow up`}, {name: 'Zelena', title: 'The Wicked Witch'}, ], }, } // const {} = info // <-- replace the next few `const` lines with this const title = info.title const protagonistName = info.protagonist.name const enemy = info.protagonist.enemies[3] const enemyTitle = enemy.title const enemyName = enemy.name return `${enemyName} (${enemyTitle}) is an enemy to ${protagonistName} in "${title}"` }
Default values of parameters
This is another feature I've been using: a very powerful way to declaratively Express function defaults.
// add(1) // add(1, 2) function add(a, b = 0) { return a + b } // is the same as const add = (a, b = 0) => a + b // is the same as function add(a, b) { b = b === undefined ? 0 : b return a + b } // in React: function useLocalStorageState({ key, initialValue, serialize = v => v, deserialize = v => v, }) { const [state, setState] = React.useState( () => deserialize(window.localStorage.getItem(key)) || initialValue, ) const serializedState = serialize(state) React.useEffect(() => { window.localStorage.setItem(key, serializedState) }, [key, serializedState]) return [state, setState] }
Rest/Spread
... grammar can be thought of as a "set" grammar, which runs on a set of values. I've been using it all the time and I strongly recommend that you study as well. It actually has different meanings in different environments, so learning those nuances will help you.
const arr = [5, 6, 8, 4, 9] Math.max(...arr) // is the same as Math.max.apply(null, arr) const obj1 = { a: 'a from obj1', b: 'b from obj1', c: 'c from obj1', d: { e: 'e from obj1', f: 'f from obj1', }, } const obj2 = { b: 'b from obj2', c: 'c from obj2', d: { g: 'g from obj2', h: 'g from obj2', }, } console.log({...obj1, ...obj2}) // is the same as console.log(Object.assign({}, obj1, obj2)) function add(first, ...rest) { return rest.reduce((sum, next) => sum + next, first) } // is the same as function add() { const first = arguments[0] const rest = Array.from(arguments).slice(1) return rest.reduce((sum, next) => sum + next, first) } // in React: function Box({className, ...restOfTheProps}) { const defaultProps = { className: `box ${className}`, children: 'Empty box', } return <div {...defaultProps} {...restOfTheProps} /> }
ESModules
If you're building your own program with modern tools, it should be able to support modules, and it's a good idea to understand how grammar works, because all or even trivial programs may need modules to reuse code.
export default function add(a, b) { return a + b } /* * import add from './add' * console.assert(add(3, 2) === 5) */ export const foo = 'bar' /* * import {foo} from './foo' * console.assert(foo === 'bar') */ export function subtract(a, b) { return a - b } export const now = new Date() /* * import {subtract, now} from './stuff' * console.assert(subtract(4, 2) === 2) * console.assert(now instanceof Date) */ // in React: import React, {Suspense, Fragment} from 'react'
Ternary expression
I like ternary expressions. Their statement is beautiful. Especially in JSX.
const message = bottle.fullOfSoda ? 'The bottle has soda!' : 'The bottle may not have soda :-(' // is the same as let message if (bottle.fullOfSoda) { message = 'The bottle has soda!' } else { message = 'The bottle may not have soda :-(' } // in React: function TeddyBearList({teddyBears}) { return ( <React.Fragment> {teddyBears.length ? ( <ul> {teddyBears.map(teddyBear => ( <li key={teddyBear.id}> <span>{teddyBear.name}</span> </li> ))} </ul> ) : ( <div>There are no teddy bears. The sadness.</div> )} </React.Fragment> ) }
I realized that prettier Before appearing and cleaning up our code, some people have to spend time figuring out what a ternary operator is, which makes ternary expressions obnoxious. If you haven't used prettier yet, I strongly recommend that you do so. Prettier will make your ternary expressions easier to read.
MDN: Conditional (Ternary) Operator
Array method
Array is great. I always use array method! The following are my common methods:
- find
- some
- every
- includes
- map
- filter
- reduce
Here are some examples:
const dogs = [ { id: 'dog-1', name: 'Poodle', temperament: [ 'Intelligent', 'Active', 'Alert', 'Faithful', 'Trainable', 'Instinctual', ], }, { id: 'dog-2', name: 'Bernese Mountain Dog', temperament: ['Affectionate', 'Intelligent', 'Loyal', 'Faithful'], }, { id: 'dog-3', name: 'Labrador Retriever', temperament: [ 'Intelligent', 'Even Tempered', 'Kind', 'Agile', 'Outgoing', 'Trusting', 'Gentle', ], }, ] dogs.find(dog => dog.name === 'Bernese Mountain Dog') // {id: 'dog-2', name: 'Bernese Mountain Dog', ...etc} dogs.some(dog => dog.temperament.includes('Aggressive')) // false dogs.some(dog => dog.temperament.includes('Trusting')) // true dogs.every(dog => dog.temperament.includes('Trusting')) // false dogs.every(dog => dog.temperament.includes('Intelligent')) // true dogs.map(dog => dog.name) // ['Poodle', 'Bernese Mountain Dog', 'Labrador Retriever'] dogs.filter(dog => dog.temperament.includes('Faithful')) // [{id: 'dog-1', ..etc}, {id: 'dog-2', ...etc}] dogs.reduce((allTemperaments, dog) => { return [...allTemperaments, ...dog.temperaments] }, []) // [ 'Intelligent', 'Active', 'Alert', ...etc ] // in React: function RepositoryList({repositories, owner}) { return ( <ul> {repositories .filter(repo => repo.owner === owner) .map(repo => ( <li key={repo.id}>{repo.name}</li> ))} </ul> ) }
Promises and async/await
It's a big topic, and you can spend more time on them. Promises are ubiquitous in the JavaScript ecosystem, and because React is deeply rooted in the ecosystem, they are almost everywhere (in fact, React itself uses promises internally).
Promises can help you manage asynchronous code. Async/await grammar is a special grammar for handling promises. The two complement each other.
function promises() { const successfulPromise = timeout(100).then(result => `success: ${result}`) const failingPromise = timeout(200, true).then(null, error => Promise.reject(`failure: ${error}`), ) const recoveredPromise = timeout(300, true).then(null, error => Promise.resolve(`failed and recovered: ${error}`), ) successfulPromise.then(log, logError) failingPromise.then(log, logError) recoveredPromise.then(log, logError) } function asyncAwaits() { async function successfulAsyncAwait() { const result = await timeout(100) return `success: ${result}` } async function failedAsyncAwait() { const result = await timeout(200, true) return `failed: ${result}` } async function recoveredAsyncAwait() { let result try { result = await timeout(300, true) return `failed: ${result}` // this would not be executed } catch (error) { return `failed and recovered: ${error}` } } successfulAsyncAwait().then(log, logError) failedAsyncAwait().then(log, logError) recoveredAsyncAwait().then(log, logError) } function log(...args) { console.log(...args) } function logError(...args) { console.error(...args) } // This is the mothership of all things asynchronous function timeout(duration = 0, shouldReject = false) { return new Promise((resolve, reject) => { setTimeout(() => { if (shouldReject) { reject(`rejected after ${duration}ms`) } else { resolve(`resolved after ${duration}ms`) } }, duration) }) } // in React: function GetGreetingForSubject({subject}) { const [isLoading, setIsLoading] = React.useState(false) const [error, setError] = React.useState(null) const [greeting, setGreeting] = React.useState(null) React.useEffect(() => { async function fetchGreeting() { try { const response = await window.fetch('https://example.com/api/greeting') const data = await response.json() setGreeting(data.greeting) } catch (error) { setError(error) } finally { setIsLoading(false) } } setIsLoading(true) fetchGreeting() }, []) return isLoading ? ( 'loading...' ) : error ? ( 'ERROR!' ) : greeting ? ( <div> {greeting} {subject} </div> ) : null }
conclusion
Of course, there are many language functions that are useful in building React applications. These are my favorites, and I find myself using them over and over again. I hope it will help you.
Wechat Public Number: Front-end Pioneer
Welcome to scan the two-dimensional code, pay attention to the public number, and push you fresh front-end technical articles every day.
Welcome to continue reading other highly praised articles in this column:
- Deep Understanding of Shadow DOM v1
- Step by step teach you how to use WebVR to implement virtual reality games
- Thirteen Modern CSS Frameworks to Improve your Development Efficiency
- Fast Start Bootstrap Vue
- How does the JavaScript engine work? Everything you need to know from call stack to Promise
- WebSocket Reality: Real-time Communication between Node and React
- 20 interview questions about Git
- In-depth analysis of Node.js console.log
- What exactly is Node.js?
- Build an API server with Node.js in 30 minutes
- Object Copy of Javascript
- Programmers earn less than 30K a month before they are 30 years old. Where to go?
- 14 Best JavaScript Data Visualization Libraries
- Eight top-level VS Code extension plug-ins for the front end
- Complete guide to Node.js multithreading
- Four Solutions and Implementation of Converting HTML to PDF