react 示例_2020年的React Cheatsheet(+真实示例)

react 示例

I've put together for you an entire visual cheatsheet of all of the concepts and skills you need to master React in 2020.

我为您汇总了2020年掌握React所需的所有概念和技能的完整视觉摘要。

But don't let the label 'cheatsheet' fool you. This is more than a mere summary of React's features.

但不要让标签“备忘单”蒙骗您。 这不仅仅是React功能的总结。

My aim here was to clearly and concisely put forth the knowledge and patterns I've gained through working with React as a professional developer.

我的目的是清楚,简洁地提出通过与React作为专业开发人员合作而获得的知识和模式。

Each part is designed to be immensely helpful by showing you real-world, practical examples with meaningful comments to guide you along the way.

通过向您展示真实实用的示例以及有意义的注释来指导您的工作,每个部分都将为您提供极大的帮助。

想要自己的副本? 📄 (Want Your Own Copy? 📄)

Grab the PDF cheatsheet right here (it takes 5 seconds).

此处获取PDF速查表(需要5秒钟)。

Here are some quick wins from grabbing the downloadable version:

从下载可下载版本中可以快速获得一些好处:

  • ✓ Quick reference guide to review however and whenever

    ✓快速参考指南,可随时随地进行审核
  • ✓ Tons of copyable code snippets for easy reuse

    ✓大量可复制的代码片段,易于重用
  • ✓ Read this massive guide wherever suits you best. On the train, at your desk, standing in line... anywhere.

    ✓阅读最适合您的详细指南。 在火车上,在您的办公桌前,在任何地方排队。
Note: There is limited coverage of class components in this cheatsheet. Class components are still valuable to know for existing React projects, but since the arrival of Hooks in 2018, we are able to make our apps with function components alone. I wanted to give beginners and experienced developers alike a Hooks-first approach treatment of React.
注意:本备忘单中类组件的覆盖范围有限。 对于现有的React项目,类组件仍然是有价值的知识,但是自从Hooks在2018年问世以来,我们就能够使我们的应用程序仅包含功能组件。 我想给初学者和经验丰富的开发人员一样对Hooks的Hooks优先方法的对待。

There's a ton of great stuff to cover, so let's get started.

有很多很棒的东西要介绍,所以让我们开始吧。

目录 (Table of Contents)

核心概念 (Core Concepts)

  • Elements and JS

    元素和JS
  • Components and Props

    组件和道具
  • Lists and Keys

    列表和键
  • Events and Event Handlers

    事件和事件处理程序

React钩 (React Hooks)

  • State and useState

    状态和使用状态
  • Side Effects and useEffect

    副作用和使用效果
  • Performance and useCallback

    性能和使用回调
  • Memoization and useMemo

    备注和使用备注
  • Refs and useRef

    参考和使用参考

高级挂钩 (Advanced Hooks)

  • Context and useContext

    上下文和useContext
  • Reducers and useReducer

    减速器及使用
  • Writing custom hooks

    编写自定义钩子
  • Rules of hooks

    钩子规则

核心概念 (Core Concepts)

Elements和JSX (Elements and JSX)

This is the basic syntax for a React element:

这是React元素的基本语法:

// In a nutshell, JSX allows us to write HTML in our JS
// JSX can use any valid html tags (i.e. div/span, h1-h6, form/input, etc)
<div>Hello React</div>

JSX elements are expressions:

JSX元素是表达式:

// as an expression, JSX can be assigned to variables...
const greeting = <div>Hello React</div>;const isNewToReact = true;// ... or can be displayed conditionally
function sayGreeting() {if (isNewToReact) {// ... or returned from functions, etc.return greeting; // displays: Hello React} else {return <div>Hi again, React</div>;}
}

JSX allows us to nest expressions:

JSX允许我们嵌套表达式:

const year = 2020;
// we can insert primitive JS values in curly braces: {}
const greeting = <div>Hello React in {year}</div>;
// trying to insert objects will result in an error

JSX allows us to nest elements:

JSX允许我们嵌套元素:

// to write JSX on multiple lines, wrap in parentheses: ()
const greeting = (// div is the parent element<div>{/* h1 and p are child elements */}<h1>Hello!</h1><p>Welcome to React</p></div>
);
// 'parents' and 'children' are how we describe JSX elements in relation
// to one another, like we would talk about HTML elements

HTML and JSX have a slightly different syntax:

HTML和JSX的语法略有不同:

// Empty div is not <div></div> (HTML), but <div/> (JSX)
<div/>// A single tag element like input is not <input> (HTML), but <input/> (JSX)
<input name="email" />// Attributes are written in camelcase for JSX (like JS variables
<button className="submit-button">Submit</button> // not 'class' (HTML)

The most basic React app requires three things:

最基本的React应用程序需要三件事:

  • ReactDOM.render() to render our app

    ReactDOM.render()渲染我们的应用
  • A JSX element (called a root node in this context)

    JSX元素(在此上下文中称为根节点)
  • A DOM element within which to mount the app (usually a div with an id of root in an index.html file)

    一个要在其中安装应用程序的DOM元素(通常是index.html文件中ID为root的div)
// imports needed if using NPM package; not if from CDN links
import React from "react";
import ReactDOM from "react-dom";const greeting = <h1>Hello React</h1>;// ReactDOM.render(root node, mounting point)
ReactDOM.render(greeting, document.getElementById("root"));

组件和道具 (Components and Props)

This is the syntax for a basic React component:

这是基本的React组件的语法:

import React from "react";// 1st component type: function component
function Header() {// function components must be capitalized unlike normal JS functions// note the capitalized name here: 'Header'return <h1>Hello React</h1>;
}// function components with arrow functions are also valid
const Header = () => <h1>Hello React</h1>;// 2nd component type: class component
// (classes are another type of function)
class Header extends React.Component {// class components have more boilerplate (with extends and render method)render() {return <h1>Hello React</h1>;}
}

This is how components are used:

这是组件的使用方式:

// do we call these function components like normal functions?// No, to execute them and display the JSX they return...
const Header = () => <h1>Hello React</h1>;// ...we use them as 'custom' JSX elements
ReactDOM.render(<Header />, document.getElementById("root"));
// renders: <h1>Hello React</h1>

Components can be reused across our app:

组件可以在我们的应用程序中重复使用:

// for example, this Header component can be reused in any app page// this component shown for the '/' route
function IndexPage() {return (<div><Header /><Hero /><Footer /></div>);
}// shown for the '/about' route
function AboutPage() {return (<div><Header /><About /><Testimonials /><Footer /></div>);
}

Data can be dynamically passed to components with props:

数据可以通过props动态传递给组件:

// What if we want to pass data to our component from a parent?
// I.e. to pass a user's name to display in our Header?const username = "John";// we add custom 'attributes' called props
ReactDOM.render(<Header username={username} />,document.getElementById("root")
);
// we called this prop 'username', but can use any valid JS identifier// props is the object that every component receives as an argument
function Header(props) {// the props we make on the component (i.e. username)// become properties on the props objectreturn <h1>Hello {props.username}</h1>;
}

Props must never be directly changed (mutated):

道具绝不能直接更改(变异):

// Components must ideally be 'pure' functions.
// That is, for every input, we be able to expect the same output// we cannot do the following with props:
function Header(props) {// we cannot mutate the props object, we can only read from itprops.username = "Doug";return <h1>Hello {props.username}</h1>;
}
// But what if we want to modify a prop value that comes in?
// That's where we would use state (see the useState section)

Children props are useful if we want to pass elements / components as props to other components.

如果我们想将元素/组件作为道具传递给其他组件,则子道具很有用。

// Can we accept React elements (or components) as props?
// Yes, through a special property on the props object called 'children'function Layout(props) {return <div className="container">{props.children}</div>;
}// The children prop is very useful for when you want the same
// component (such as a Layout component) to wrap all other components:
function IndexPage() {return (<Layout><Header /><Hero /><Footer /></Layout>);
}// different page, but uses same Layout component (thanks to children prop)
function AboutPage() {return (<Layout><About /><Footer /></Layout>);
}

Conditionally displaying components with ternaries and short-circuiting:

有条件地显示具有三元和短路的组件:

// if-statements are fine to conditionally show , however...
// ...only ternaries (seen below) allow us to insert these conditionals
// in JSX, however
function Header() {const isAuthenticated = checkAuth();return (<nav><Logo />{/* if isAuth is true, show AuthLinks. If false, Login  */}{isAuthenticated ? <AuthLinks /> : <Login />}{/* if isAuth is true, show Greeting. If false, nothing. */}{isAuthenticated && <Greeting />}</nav>);
}

Fragments are special components for displaying multiple components without adding an extra element to the DOM.

片段是特殊的组件,用于显示多个组件,而无需向DOM添加额外的元素。

Fragments are ideal for conditional logic:

片段是条件逻辑的理想选择:

// we can improve the logic in the previous example
// if isAuthenticated is true, how do we display both AuthLinks and Greeting?
function Header() {const isAuthenticated = checkAuth();return (<nav><Logo />{/* we can render both components with a fragment */}{/* fragments are very concise: <> </> */}{isAuthenticated ? (<><AuthLinks /><Greeting /></>) : (<Login />)}</nav>);
}

列表和键 (Lists and Keys)

Use .map() to convert lists of data (arrays) into lists of elements:

使用.map()将数据(数组)列表转换为元素列表:

const people = ["John", "Bob", "Fred"];
const peopleList = people.map(person => <p>{person}</p>);

.map() is also used for components as well as elements:

.map()也用于组件和元素:

function App() {const people = ['John', 'Bob', 'Fred'];// can interpolate returned list of elements in {}return (<ul>{/* we're passing each array element as props */}{people.map(person => <Person name={person} />}</ul>);
}function Person({ name }) {// gets 'name' prop using object destructuringreturn <p>this person's name is: {name}</p>;
}

Each React element iterated over needs a special 'key' prop. Keys are essential for React to be able to keep track of each element that is being iterated over with map

每个迭代的React元素都需要一个特殊的“关键”道具。 密钥对于React至关重要,以便能够跟踪正在被map迭代的每个元素

Without keys, it is harder for it to figure out how elements should be updated when data changes.

如果没有键,则很难确定在数据更改时应如何更新元素。

Keys should be unique values to represent the fact that these elements are separate from one another.

键应该是唯一的值,以表示这些元素彼此分开的事实。

function App() {const people = ['John', 'Bob', 'Fred'];return (<ul>{/* keys need to be primitive values, ideally a generated id */}{people.map(person => <Person key={person} name={person} />)}</ul>);
}// If you don't have ids with your set of data or unique primitive values,
// you can use the second parameter of .map() to get each elements index
function App() {const people = ['John', 'Bob', 'Fred'];return (<ul>{/* use array element index for key */}{people.map((person, i) => <Person key={i} name={person} />)}</ul>);
}

事件和事件处理程序 (Events and Event Handlers)

Events in React and HTML are slightly different.

React和HTML中的事件略有不同。

// Note: most event handler functions start with 'handle'
function handleToggleTheme() {// code to toggle app theme
}// in html, onclick is all lowercase
<button onclick="handleToggleTheme()">Submit
</button>// in JSX, onClick is camelcase, like attributes / props
// we also pass a reference to the function with curly braces
<button onClick={handleToggleTheme}>Submit
</button>

The most essential React events to know are onClick and onChange.

要了解的最重要的React事件是onClick和onChange。

  • onClick handles click events on JSX elements (namely buttons)

    onClick处理JSX元素(即按钮)上的点击事件
  • onChange handles keyboard events (namely inputs)

    onChange处理键盘事件(即输入)
function App() {function handleChange(event) {// when passing the function to an event handler, like onChange// we get access to data about the event (an object)const inputText = event.target.value;const inputName = event.target.name; // myInput// we get the text typed in and other data from event.target}function handleSubmit() {// on click doesn't usually need event data}return (<div><input type="text" name="myInput" onChange={handleChange} /><button onClick={handleSubmit}>Submit</button></div>);
}

React钩 (React Hooks)

状态和使用状态 (State and useState)

useState gives us local state in a function component:

useState在函数组件中为我们提供本地状态:

import React from 'react';// create state variable
// syntax: const [stateVariable] = React.useState(defaultValue);
function App() {const [language] = React.useState('javascript');// we use array destructuring to declare state variablereturn <div>I am learning {language}</div>;
}

Note: Any hook in this section is from the React package and can be imported individually.

注意:本节中的任何钩子都来自React包,可以单独导入。

import React, { useState } from "react";function App() {const [language] = useState("javascript");return <div>I am learning {language}</div>;
}

useState also gives us a 'setter' function to update the state it creates:

useState还为我们提供了一个“设置器”功能来更新其创建的状态:

function App() {// the setter function is always the second destructured valueconst [language, setLanguage] = React.useState("python");// the convention for the setter name is 'setStateVariable'return (<div>{/*  why use an arrow function here instead onClick={setterFn()} ? */}<button onClick={() => setLanguage("javascript")}>Change language to JS</button>{/*  if not, setLanguage would be called immediately and not on click */}<p>I am now learning {language}</p></div>);
}// note that whenever the setter function is called, the state updates,
// and the App component re-renders to display the new state

useState can be used once or multiple times within a single component:

useState可以在单个组件中使用一次或多次:

function App() {const [language, setLanguage] = React.useState("python");const [yearsExperience, setYearsExperience] = React.useState(0);return (<div><button onClick={() => setLanguage("javascript")}>Change language to JS</button><inputtype="number"value={yearsExperience}onChange={event => setYearsExperience(event.target.value)}/><p>I am now learning {language}</p><p>I have {yearsExperience} years of experience</p></div>);
}

useState can accept primitive or object values to manage state:

useState可以接受原始值或对象值来管理状态:

// we have the option to organize state using whatever is the
// most appropriate data type, according to the data we're tracking
function App() {const [developer, setDeveloper] = React.useState({language: "",yearsExperience: 0});function handleChangeYearsExperience(event) {const years = event.target.value;// we must pass in the previous state object we had with the spread operatorsetDeveloper({ ...developer, yearsExperience: years });}return (<div>{/* no need to get prev state here; we are replacing the entire object */}<buttononClick={() =>setDeveloper({language: "javascript",yearsExperience: 0})}>Change language to JS</button>{/* we can also pass a reference to the function */}<inputtype="number"value={developer.yearsExperience}onChange={handleChangeYearsExperience}/><p>I am now learning {developer.language}</p><p>I have {developer.yearsExperience} years of experience</p></div>);
}

If the new state depends on the previous state, to guarantee that the update is done reliably, we can use a function within the setter function that gives us the correct previous state.

如果新状态依赖于先前状态,则为保证可靠地完成更新,我们可以在setter函数中使用一个函数,该函数为我们提供正确的先前状态。

function App() {const [developer, setDeveloper] = React.useState({language: "",yearsExperience: 0,isEmployed: false});function handleToggleEmployment(event) {// we get the previous state variable's value in the parameters// we can name 'prevState' however we likesetDeveloper(prevState => {return { ...prevState, isEmployed: !prevState.isEmployed };// it is essential to return the new state from this function});}return (<button onClick={handleToggleEmployment}>Toggle Employment Status</button>);
}

副作用和使用效果 (Side effects and useEffect)

useEffect lets us perform side effects in function components. So what are side effects?

useEffect让我们在功能组件中执行副作用。 那么什么是副作用呢?

  • Side effects are where we need to reach into the outside world. For example, fetching data from an API or working with the DOM.

    副作用是我们需要接触外界的地方。 例如,从API提取数据或使用DOM。
  • Side effects are actions that can change our component state in an unpredictable fashion (that have caused 'side effects').

    副作用是可以以不可预测的方式更改组件状态的动作(已引起“副作用”)。

useEffect accepts a callback function (called the 'effect' function), which will by default run every time there is a re-render. It runs once our component mounts, which is the right time to perform a side effect in the component lifecycle.

useEffect接受一个回调函数(称为“效果”函数),默认情况下,它将在每次重新渲染时运行。 一旦我们的组件安装好,它就会运行,这是在组件生命周期中产生副作用的正确时机。

// what does our code do? Picks a color from the colors array
// and makes it the background color
function App() {const [colorIndex, setColorIndex] = React.useState(0);const colors = ["blue", "green", "red", "orange"];// we are performing a 'side effect' since we are working with an API// we are working with the DOM, a browser API outside of ReactuseEffect(() => {document.body.style.backgroundColor = colors[colorIndex];});// whenever state is updated, App re-renders and useEffect runsfunction handleChangeIndex() {const next = colorIndex + 1 === colors.length ? 0 : colorIndex + 1;setColorIndex(next);}return <button onClick={handleChangeIndex}>Change background color</button>;
}

To avoid executing the effect callback after each render, we provide a second argument, an empty array:

为了避免在每次渲染后执行效果回调,我们提供了第二个参数,一个空数组:

function App() {...// now our button doesn't work no matter how many times we click it...useEffect(() => {document.body.style.backgroundColor = colors[colorIndex];}, []);// the background color is only set once, upon mount// how do we not have the effect function run for every state update...// but still have it work whenever the button is clicked?return (<button onClick={handleChangeIndex}>Change background color</button>);
}

useEffect lets us conditionally perform effects with the dependencies array.

useEffect让我们有条件地执行依赖关系数组的效果。

The dependencies array is the second argument, and if any one of the values in the array changes, the effect function runs again.

依赖项数组是第二个参数,如果数组中的任何值发生更改,效果函数都会再次运行。

function App() {const [colorIndex, setColorIndex] = React.useState(0);const colors = ["blue", "green", "red", "orange"];// we add colorIndex to our dependencies array// when colorIndex changes, useEffect will execute the effect fn againuseEffect(() => {document.body.style.backgroundColor = colors[colorIndex];// when we use useEffect, we must think about what state values// we want our side effect to sync with}, [colorIndex]);function handleChangeIndex() {const next = colorIndex + 1 === colors.length ? 0 : colorIndex + 1;setColorIndex(next);}return <button onClick={handleChangeIndex}>Change background color</button>;
}

useEffect lets us unsubscribe from certain effects by returning a function at the end:

useEffect让我们通过在最后返回一个函数来取消订阅某些效果:

function MouseTracker() {const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 });React.useEffect(() => {// .addEventListener() sets up an active listener...window.addEventListener("mousemove", event => {const { pageX, pageY } = event;setMousePosition({ x: pageX, y: pageY });});// ...so when we navigate away from this page, it needs to be// removed to stop listening. Otherwise, it will try to set// state in a component that doesn't exist (causing an error)// We unsubscribe any subscriptions / listeners w/ this 'cleanup function'return () => {window.removeEventListener("mousemove", event => {const { pageX, pageY } = event;setMousePosition({ x: pageX, y: pageY });});};}, []);return (<div><h1>The current mouse position is:</h1><p>X: {mousePosition.x}, Y: {mousePosition.y}</p></div>);
}// Note: we could extract the reused logic in the callbacks to
// their own function, but I believe this is more readable
  • Fetching data with useEffect

    使用useEffect获取数据

Note that handling promises with the more concise async/await syntax requires creating a separate function. (Why? The effect callback function cannot be async.)

请注意,使用更简洁的async / await语法处理Promise需要创建一个单独的函数。 (为什么?效果回调函数不能异步。)

const endpoint = "https://api.github.com/users/codeartistryio";// with promises:
function App() {const [user, setUser] = React.useState(null);React.useEffect(() => {// promises work in callbackfetch(endpoint).then(response => response.json()).then(data => setUser(data));}, []);
}// with async / await syntax for promise:
function App() {const [user, setUser] = React.useState(null);// cannot make useEffect callback function asyncReact.useEffect(() => {getUser();}, []);// instead, use async / await in separate function, then call// function back in useEffectasync function getUser() {const response = await fetch("https://api.github.com/codeartistryio");const data = await response.json();setUser(data);}
}

性能和使用回调 (Performance and useCallback)

useCallback is a hook that is used for improving our component's performance.

useCallback是一个挂钩,用于提高组件的性能。

If you have a component that re-renders frequently, useCallback prevents callback functions within the component from being recreated every single time the component re-renders (which means the function component re-runs).

如果您有一个频繁重新渲染的组件,则useCallback防止在每次重新渲染组件时重新创建该组件内的回调函数(这意味着该函数组件重新运行)。

useCallback re-runs only when one of it's dependencies changes.

useCallback仅在其中一项依赖项更改时才重新运行。

// in Timer, we are calculating the date and putting it in state a lot
// this results in a re-render for every state update// we had a function handleIncrementCount to increment the state 'count'...
function Timer() {const [time, setTime] = React.useState();const [count, setCount] = React.useState(0);// ... but unless we wrap it in useCallback, the function is// recreated for every single re-render (bad performance hit)// useCallback hook returns a callback that isn't recreated every timeconst inc = React.useCallback(function handleIncrementCount() {setCount(prevCount => prevCount + 1);},// useCallback accepts a second arg of a dependencies array like useEffect// useCallback will only run if any dependency changes (here it's 'setCount')[setCount]);React.useEffect(() => {const timeout = setTimeout(() => {const currentTime = JSON.stringify(new Date(Date.now()));setTime(currentTime);}, 300);return () => {clearTimeout(timeout);};}, [time]);return (<div><p>The current time is: {time}</p><p>Count: {count}</p><button onClick={inc}>+</button></div>);
}

备注和使用备注 (Memoization and useMemo)

useMemo is very similar to useCallback and is for improving performance. But instead of being for callbacks, it is for storing the results of expensive calculations.

useMemo与useCallback非常相似,用于提高性能。 但是,它不是用于回调,而是用于存储昂贵的计算结果。

useMemo allows us to 'memoize', or remember the result of expensive calculations when they have already been made for certain inputs (we already did it once for these values, so it's nothing new to do it again).

useMemo允许我们“记忆”,或记住已经为某些输入进行了昂贵的计算的结果(我们已经对这些值进行了一次,因此再做一次并不是什么新鲜事)。

useMemo returns a value from the computation, not a callback function (but can be a function).

useMemo从计算中返回一个值,而不是回调函数(但可以是一个函数)。

// useMemo is useful when we need a lot of computing resources
// to perform an operation, but don't want to repeat it on each re-renderfunction App() {// state to select a word in 'words' array belowconst [wordIndex, setWordIndex] = useState(0);// state for counterconst [count, setCount] = useState(0);// words we'll use to calculate letter countconst words = ["i", "am", "learning", "react"];const word = words[wordIndex];function getLetterCount(word) {// we mimic expensive calculation with a very long (unnecessary) looplet i = 0;while (i < 1000000) i++;return word.length;}// Memoize expensive function to return previous value if input was the same// only perform calculation if new word without a cached valueconst letterCount = React.useMemo(() => getLetterCount(word), [word]);// if calculation was done without useMemo, like so:// const letterCount = getLetterCount(word);// there would be a delay in updating the counter// we would have to wait for the expensive function to finishfunction handleChangeIndex() {// flip from one word in the array to the nextconst next = wordIndex + 1 === words.length ? 0 : wordIndex + 1;setWordIndex(next);}return (<div><p>{word} has {letterCount} letters</p><button onClick={handleChangeIndex}>Next word</button><p>Counter: {count}</p><button onClick={() => setCount(count + 1)}>+</button></div>);
}

参考和使用参考 (Refs and useRef)

Refs are a special attribute that are available on all React components. They allow us to create a reference to a given element / component when the component mounts

引用是一个特殊属性,可在所有React组件上使用。 它们允许我们在安装组件时创建对给定元素/组件的引用

useRef allows us to easily use React refs. We call useRef (at the top of the component) and attach the returned value to the element's ref attribute to refer to it.

useRef允许我们轻松使用React refs。 我们调用useRef(在组件顶部),并将返回的值附加到元素的ref属性以引用它。

Once we create a reference, we use the current property to modify (mutate) the element's properties. Or we can call any available methods on that element (like .focus() to focus an input).

创建引用后,我们将使用当前属性来修改(变异)元素的属性。 或者,我们可以在该元素上调用任何可用的方法(例如.focus()来使输入集中)。

function App() {const [query, setQuery] = React.useState("react hooks");// we can pass useRef a default value// we don't need it here, so we pass in null to ref an empty objectconst searchInput = useRef(null);function handleClearSearch() {// current references the text input once App mountssearchInput.current.value = "";// useRef can store basically any value in its .current propertysearchInput.current.focus();}return (<form><inputtype="text"onChange={event => setQuery(event.target.value)}ref={searchInput}/><button type="submit">Search</button><button type="button" onClick={handleClearSearch}>Clear</button></form>);
}

高级挂钩 (Advanced Hooks)

上下文和useContext (Context and useContext)

In React, we want to avoid the following problem of creating multiple props to pass data down two or more levels from a parent component:

在React中,我们希望避免以下问题:创建多个道具以将数据从父组件向下传递到两个或多个级别:

// Context helps us avoid creating multiple duplicate props
// This pattern is also called props drilling:
function App() {// we want to pass user data down to Headerconst [user] = React.useState({ name: "Fred" });return ({/* first 'user' prop */}<Main user={user} />);
}const Main = ({ user }) => (<>{/* second 'user' prop */}<Header user={user} /><div>Main app content...</div></>
);const Header = ({ user }) => <header>Welcome, {user.name}!</header>;

Context is helpful for passing props down multiple levels of child components from a parent component.

上下文有助于将道具从父组件向下传递到多个子组件级别。

// Here is the previous example rewritten with Context
// First we create context, where we can pass in default values
const UserContext = React.createContext();
// we call this 'UserContext' because that's what data we're passing downfunction App() {// we want to pass user data down to Headerconst [user] = React.useState({ name: "Fred" });return ({/* we wrap the parent component with the provider property */}{/* we pass data down the computer tree w/ value prop */}<UserContext.Provider value={user}><Main /></UserContext.Provider>);
}const Main = () => (<><Header /><div>Main app content...</div></>
);// we can remove the two 'user' props, we can just use consumer
// to consume the data where we need it
const Header = () => ({/* we use this pattern called render props to get access to the data*/}<UserContext.Consumer>{user => <header>Welcome, {user.name}!</header>}</UserContext.Consumer>
);

The useContext hook can remove this unusual-looking render props pattern, however, to be able to consume context in whatever function component we like:

useContext钩子可以删除这种看起来异常的渲染道具模式,以便能够在我们喜欢的任何函数组件中使用上下文:

const Header = () => {// we pass in the entire context object to consume itconst user = React.useContext(UserContext);// and we can remove the Consumer tagsreturn <header>Welcome, {user.name}!</header>;
};

减速器及使用 (Reducers and useReducer)

Reducers are simple, predictable (pure) functions that take a previous state object and an action object and return a new state object. For example:

约简器是简单,可预测(纯)的函数,它们采用先前的状态对象和操作对象并返回新的状态对象。 例如:

// let's say this reducer manages user state in our app:
function reducer(state, action) {// reducers often use a switch statement to update state// in one way or another based on the action's type propertyswitch (action.type) {// if action.type has the string 'LOGIN' on itcase "LOGIN":// we get data from the payload object on actionreturn { username: action.payload.username, isAuth: true };case "SIGNOUT":return { username: "", isAuth: false };default:// if no case matches, return previous statereturn state;}
}

Reducers are a powerful pattern for managing state that is used in the popular state management library Redux (common used with React).

Reducer是一种流行的状态管理库Redux(与React共同使用)中用于管理状态的强大模式。

Reducers can be used in React with the useReducer hook in order to manage state across our app, as compared to useState (which is for local component state).

与useState(用于本地组件状态)相比,Reducer可与useReducer挂钩一起在React中使用,以管理整个应用程序中的状态。

useReducer can be paired with useContext to manage data and pass it around components easily.

可以将useReducer与useContext配对使用,以管理数据并轻松地将其传递给组件。

Thus useReducer + useContext can be an entire state management system for our apps.

因此useReducer + useContext可以成为我们应用程序的整个状态管理系统。

const initialState = { username: "", isAuth: false };function reducer(state, action) {switch (action.type) {case "LOGIN":return { username: action.payload.username, isAuth: true };case "SIGNOUT":// could also spread in initialState herereturn { username: "", isAuth: false };default:return state;}
}function App() {// useReducer requires a reducer function to use and an initialStateconst [state, dispatch] = useReducer(reducer, initialState);// we get the current result of the reducer on 'state'// we use dispatch to 'dispatch' actions, to run our reducer// with the data it needs (the action object)function handleLogin() {dispatch({ type: "LOGIN", payload: { username: "Ted" } });}function handleSignout() {dispatch({ type: "SIGNOUT" });}return (<>Current user: {state.username}, isAuthenticated: {state.isAuth}<button onClick={handleLogin}>Login</button><button onClick={handleSignout}>Signout</button></>);
}

编写自定义钩子 (Writing custom hooks)

Hooks were created to easily reuse behavior between components.

创建挂钩是为了轻松重用组件之间的行为。

They're a more understandable pattern than previous ones for class components, such as higher-order components or render props

对于类组件(例如高阶组件或渲染道具),它们是比以前的模式更易于理解的模式

What's great is that we can create our own hooks according to our own projects' needs, aside from the ones we've covered that React provides:

很棒的是,除了我们已经介绍的React提供的那些功能之外,我们还可以根据自己项目的需要创建自己的钩子:

// here's a custom hook that is used to fetch data from an API
function useAPI(endpoint) {const [value, setValue] = React.useState([]);React.useEffect(() => {getData();}, []);async function getData() {const response = await fetch(endpoint);const data = await response.json();setValue(data);};return value;
};// this is a working example! try it yourself (i.e. in codesandbox.io)
function App() {const todos = useAPI("https://todos-dsequjaojf.now.sh/todos");return (<ul>{todos.map(todo => <li key={todo.id}>{todo.text}</li>}</ul>);
}

钩子规则 (Rules of hooks)

There are two core rules of using React hooks that we cannot violate for them to work properly:

使用React挂钩有两个我们不能违反的核心规则,它们才能正常工作:

  1. Hooks can only be called at the top of components (they cannot be in conditionals, loops or nested functions)

    挂钩只能在组件的顶部调用(它们不能在条件,循环或嵌套函数中)
  2. Hooks can only be used within function components (they cannot be in normal JavaScript functions or class components)

    挂钩只能在函数组件内使用(不能在常规JavaScript函数或类组件中使用)
function checkAuth() {// Rule 2 Violated! Hooks cannot be used in normal functions, only componentsReact.useEffect(() => {getUser();}, []);
}function App() {// this is the only validly executed hook in this componentconst [user, setUser] = React.useState(null);// Rule 1 violated! Hooks cannot be used within conditionals (or loops)if (!user) {React.useEffect(() => {setUser({ isAuth: false });// if you want to conditionally execute an effect, use the// dependencies array for useEffect}, []);}checkAuth();// Rule 1 violated! Hooks cannot be used in nested functionsreturn <div onClick={() => React.useMemo(() => doStuff(), [])}>Our app</div>;
}

下一步是什么 (What's Next)

There are many other React concepts to learn, but these are the ones I believe you must know before any others to set you on the path to React mastery in 2020.

还有许多其他的React概念需要学习,但我相信您必须先了解这些概念,才能使您踏上2020年的React掌握道路。

Want a quick reference of all of these concepts?

是否需要所有这些概念的快速参考?

Download a complete PDF cheatsheet of all this info right here.

在此处下载所有这些信息的完整PDF速查表。

Keep coding and I'll catch you in the next article!

继续编码,我将在下一篇文章中帮助您!

想要成为JS大师吗? 加入2020年JS训练营 (Want To Become a JS Master? Join the 2020 JS Bootcamp )

Join the 2020 JS Bootcamp

Follow + Say Hi! 👋 Twitter • codeartistry.io

关注+说声嗨! 👋 Twitter的 • codeartistry.io

翻译自: https://www.freecodecamp.org/news/the-react-cheatsheet-for-2020/

react 示例

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/390872.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

查询数据库中有多少个数据表_您的数据中有多少汁?

查询数据库中有多少个数据表97%. That’s the percentage of data that sits unused by organizations according to Gartner, making up so-called “dark data”.97 &#xff05;。 根据Gartner的说法&#xff0c;这就是组织未使用的数据百分比&#xff0c;即所谓的“ 暗数据…

数据科学与大数据技术的案例_作为数据科学家解决问题的案例研究

数据科学与大数据技术的案例There are two myths about how data scientists solve problems: one is that the problem naturally exists, hence the challenge for a data scientist is to use an algorithm and put it into production. Another myth considers data scient…

Spring-Boot + AOP实现多数据源动态切换

2019独角兽企业重金招聘Python工程师标准>>> 最近在做保证金余额查询优化&#xff0c;在项目启动时候需要把余额全量加载到本地缓存&#xff0c;因为需要全量查询所有骑手的保证金余额&#xff0c;为了不影响主数据库的性能&#xff0c;考虑把这个查询走从库。所以涉…

leetcode 1738. 找出第 K 大的异或坐标值

本文正在参加「Java主题月 - Java 刷题打卡」&#xff0c;详情查看 活动链接 题目 给你一个二维矩阵 matrix 和一个整数 k &#xff0c;矩阵大小为 m x n 由非负整数组成。 矩阵中坐标 (a, b) 的 值 可由对所有满足 0 < i < a < m 且 0 < j < b < n 的元素…

商业数据科学

数据科学 &#xff0c; 意见 (Data Science, Opinion) “There is a saying, ‘A jack of all trades and a master of none.’ When it comes to being a data scientist you need to be a bit like this, but perhaps a better saying would be, ‘A jack of all trades and …

leetcode 692. 前K个高频单词

题目 给一非空的单词列表&#xff0c;返回前 k 个出现次数最多的单词。 返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率&#xff0c;按字母顺序排序。 示例 1&#xff1a; 输入: ["i", "love", "leetcode", "…

数据显示,中国近一半的独角兽企业由“BATJ”四巨头投资

中国的互联网行业越来越有被巨头垄断的趋势。百度、阿里巴巴、腾讯、京东&#xff0c;这四大巨头支撑起了中国近一半的独角兽企业。CB Insights日前发表了题为“Nearly Half Of China’s Unicorns Backed By Baidu, Alibaba, Tencent, Or JD.com”的数据分析文章&#xff0c;列…

Java的Servlet、Filter、Interceptor、Listener

写在前面&#xff1a; 使用Spring-Boot时&#xff0c;嵌入式Servlet容器可以通过扫描注解&#xff08;ServletComponentScan&#xff09;的方式注册Servlet、Filter和Servlet规范的所有监听器&#xff08;如HttpSessionListener监听器&#xff09;。 Spring boot 的主 Servlet…

leetcode 1035. 不相交的线(dp)

在两条独立的水平线上按给定的顺序写下 nums1 和 nums2 中的整数。 现在&#xff0c;可以绘制一些连接两个数字 nums1[i] 和 nums2[j] 的直线&#xff0c;这些直线需要同时满足满足&#xff1a; nums1[i] nums2[j] 且绘制的直线不与任何其他连线&#xff08;非水平线&#x…

SPI和RAM IP核

学习目的&#xff1a; &#xff08;1&#xff09; 熟悉SPI接口和它的读写时序&#xff1b; &#xff08;2&#xff09; 复习Verilog仿真语句中的$readmemb命令和$display命令&#xff1b; &#xff08;3&#xff09; 掌握SPI接口写时序操作的硬件语言描述流程&#xff08;本例仅…

个人技术博客Alpha----Android Studio UI学习

项目联系 这次的项目我在前端组&#xff0c;负责UI&#xff0c;下面简略讲下学到的内容和使用AS过程中遇到的一些问题及其解决方法。 常见UI控件的使用 1.TextView 在TextView中&#xff0c;首先用android:id给当前控件定义一个唯一标识符。在活动中通过这个标识符对控件进行事…

数据科学家数据分析师_站出来! 分析人员,数据科学家和其他所有人的领导和沟通技巧...

数据科学家数据分析师这一切如何发生&#xff1f; (How did this All Happen?) As I reflect on my life over the past few years, even though I worked my butt off to get into Data Science as a Product Analyst, I sometimes still find myself begging the question, …

react-hooks_在5分钟内学习React Hooks-初学者教程

react-hooksSometimes 5 minutes is all youve got. So in this article, were just going to touch on two of the most used hooks in React: useState and useEffect. 有时只有5分钟。 因此&#xff0c;在本文中&#xff0c;我们仅涉及React中两个最常用的钩子&#xff1a; …

分析工作试用期收获_免费使用零编码技能探索数据分析

分析工作试用期收获Have you been hearing the new industry buzzword — Data Analytics(it was AI-ML earlier) a lot lately? Does it sound complicated and yet simple enough? Understand the logic behind models but dont know how to code? Apprehensive of spendi…

select的一些问题。

这个要怎么统计类别数呢&#xff1f; 哇哇哇 解决了。 之前怎么没想到呢&#xff1f;感谢一楼。转载于:https://www.cnblogs.com/AbsolutelyPerfect/p/7818701.html

重学TCP协议(12)SO_REUSEADDR、SO_REUSEPORT、SO_LINGER

1. SO_REUSEADDR 假如服务端出现故障&#xff0c;主动断开连接以后&#xff0c;需要等 2 个 MSL 以后才最终释放这个连接&#xff0c;而服务重启以后要绑定同一个端口&#xff0c;默认情况下&#xff0c;操作系统的实现都会阻止新的监听套接字绑定到这个端口上。启用 SO_REUSE…

残疾科学家_数据科学与残疾:通过创新加强护理

残疾科学家Could the time it takes for you to water your houseplants say something about your health? Or might the amount you’re moving around your neighborhood reflect your mental health status?您给植物浇水所需的时间能否说明您的健康状况&#xff1f; 还是…

Linux 网络相关命令

1. telnet 1.1 检查端口是否打开 执行 telnet www.baidu.com 80&#xff0c;粘贴下面的文本&#xff08;注意总共有四行&#xff0c;最后两行为两个空行&#xff09; telnet [domainname or ip] [port]例如&#xff1a; telnet www.baidu.com 80 如果这个网络连接可达&…

spss23出现数据消失_改善23亿人口健康数据的可视化

spss23出现数据消失District Health Information Software, or DHIS2, is one of the most important sources of health data in low- and middle-income countries (LMICs). Used by 72 different LMIC governments, DHIS2 is a web-based open-source platform that is used…

01-hibernate注解:类级别注解,@Entity,@Table,@Embeddable

Entity Entity:映射实体类 Entity(name"tableName") name:可选&#xff0c;对应数据库中一个表&#xff0c;若表名与实体类名相同&#xff0c;则可以省略。 注意&#xff1a;使用Entity时候必须指定实体类的主键属性。 第一步&#xff1a;建立实体类&#xff1a; 分别…