React interrelated reference Manual

React 本教程描述一些基本概念

如果需要入门学习,推荐教程: https://reactjs.org/
本教程为了加强记忆,更改了学习的顺序。 且会收集教程以外实例。

React实现了与浏览器无关的DOM系统,以实现性能和跨浏览器的兼容性。

0. 知识

0.1,ES6 箭头函数 :

graph LR A[箭头函数] -- 没有将自己绑定到 --> B((关键词)) B --> C(arguments) B --> D{super} B --> E{new.target} B --> F{this}

箭头函数表达式的语法比函数表达式更简洁,并且没有自己的this,arguments,super或new.target。箭头函数表达式更适用于那些本来需要匿名函数的地方,并且它不能用作构造函数。

// 实例应用
const materials = [
  'Hydrogen',
  'Helium',
  'Lithium',
  'Beryllium'
];

巧妙的完成了数组长度的调用;

console.log(materials.map(material => material.length));
// expected output: Array [8, 6, 7, 9]
  • params => ({foo: bar}) 加括号的函数体返回对象字面量表达式:
  • (param1, param2, ...rest) => { statements } 【and】(param1 = defaultValue1, param2, …, paramN = defaultValueN) => {
    statements }
    支持剩余参数默认参数。如例(剩余参数):
function sum(...theArgs) {
  return theArgs.reduce((previous, current) => {
    return previous + current;
  });
}

console.log(sum(1, 2, 3));
// expected output: 6

console.log(sum(1, 2, 3, 4));
// expected output: 10
  • () => { statements } 没有参数的函数应该写成一对圆括号。
  • singleParam => { statements } 当只有一个参数时,圆括号是可选的。
  • 同样支持参数列表解构
    什么是解构?解构赋值语法是一种 Javascript 表达式。通过解构赋值, 可以将属性/值从对象/数组中取出,赋值给其他变量。
let a, b, rest;
[a, b] = [10, 20];

console.log(a);
// expected output: 10

console.log(b);
// expected output: 20

[a, b, ...rest] = [10, 20, 30, 40, 50];

console.log(rest);
// expected output: Array [30,40,50]

// ---
let f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c;
f();  
// expected output:  6

0.2,进阶指南

相关知识:

1. Component API && Component

  • react versions 使用前明确环境与使用的版本。
  • 组件类 API参考:

Props

state 和 props 主要的区别在于 props 是不可变的,而 state 可以根据与用户交互来改变。这就是为什么有些容器组件需要定义 state 来更新和修改数据。 而子组件只能通过 props 来传递数据。

function HelloMessage(props) {
    return <h1>Hello {props.name}!</h1>;
}
const element = <HelloMessage name="Runoob"/>;
ReactDOM.render(
    element,
    document.getElementById('example')
);

关于组件生命周期

每个组件都有几个“生命周期方法”,您可以重写它们以在流程中的特定时间运行代码。可以参考的生命周期图。

  • 安装时
    • static getDerivedStateFromProps() ; 在初始安装和后续更新上,调用render方法之前立即调用。
    • constructor()
      通常,在React中,constructor构造函数仅用于两个目的:
      1.通过将对象分配给来初始化本地状态this.state。
      2.将事件处理程序方法绑定到实例。
    • render()
      该render()方法是类组件中唯一需要的方法。
      调用时,它应该检查this.props并this.state返回以下类型之一:
      - React elements 元素
      - Arrays and fragments.。从渲染返回多个元素。
      - Portals. 将子级渲染到另一个DOM子树中。
      - String and numbers 字符串和数字。
      - Booleans or null 布尔值或null.
      该render()函数应该是纯函数,这意味着它不会修改组件状态,它在每次调用时都返回相同的结果,并且不与浏览器直接交互。
      如果您需要与浏览器进行交互,请改为使用componentDidMount()或其他生命周期方法执行工作。保持render()纯净使组件更容易考虑。
    • componentDidMount() ; 挂载组件(插入树中)后立即调用。需要DOM节点的初始化应在此处进行。
  • 更新时
    - static getDerivedStateFromProps()
    - shouldComponentUpdate(nextProps, nextState); 当接收到新的Props或State 时,在渲染之前调用。默认为true。
    - render()
    - componentDidUpdate(prevProps, prevState, snapshot); 更新发生后立即调用。初始渲染不调用此方法。
    - getSnapshotBeforeUpdate()
  • 卸载时
    - componentWillUnmount()
  • 错误处理
    可在其子组件树中的任何位置捕获JavaScript错误,记录这些错误并显示后备UI,而不是崩溃的组件树。错误边界会在渲染过程中,生命周期方法中及其下的整个树的构造函数中捕获错误。
    - static getDerivedStateFromError()
    后代组件引发错误后,将调用此生命周期。它接收作为参数抛出的错误,并且应返回值以更新状态。
    - componentDidCatch()
    后代组件引发错误后,将调用此生命周期。它接收两个参数:
    - error -引发的错误。
    - info-具有componentStack密钥的对象,其中包含有关哪个组件引发了错误的信息。
    componentDidCatch()在“提交”阶段调用,因此允许出现副作用。它应用于记录错误之类的事情:
  • 其它API :

     - setState()
     - forceUpdate()
    
  • 类属性
    - defaultProps
    - displayName
  • 实例属性
    - props
    - state

2. 元素渲染

<div id="root"></div>
const element = <h1>Hello, world</h1>;
ReactDOM.render(element, document.getElementById('root'));

在CodePen上尝试

它在页面上显示“ Hello,world”。

3. JSX

import React from 'react';
import React from 'react';

// Correct! This is a component and should be capitalized:
function Hello(props) {
// Correct! This use of <div> is legitimate because div is a valid HTML tag:
return <div>Hello {props.toWhat}</div>;
}

function HelloWorld() {
 // Correct! React knows <Hello /> is a component because it's capitalized.
return <Hello toWhat="World" />;
}

与浏览器的 DOM 元素不同,React 当中的元素事实上是普通的对象,React DOM 可以确保 浏览器 DOM 的数据内容与 React 元素保持一致。
要将 React 元素渲染到根 DOM 节点中,我们通过把它们都传递给 ReactDOM.render() 的方法来将其渲染到页面上:

const element = < HelloWorld />;
ReactDOM.render(element, document.getElementById('example'));  

4,This && 事件处理 Handling Events

必须谨慎对待 JSX 回调函数中的 this,在 JavaScript 中,class 的方法默认不会绑定 this。如果你忘记绑定 this.handleClick 并把它传入了 onClick,当你调用这个函数的时候 this 的值为 undefined。

HTML
    <button onclick="activateLasers()">
       Activate Lasers
     </button>
在React中略有不同:
    <button onClick={activateLasers}>
      Activate Lasers
    </button>

使用React时,通常不需要addEventListener在创建DOM元素后调用将侦听器添加到DOM元素。相反,仅在最初呈现元素时提供一个侦听器。

此Toggle组件呈现一个按钮,该按钮使用户可以在“ ON”和“ OFF”状态之间切换:
class Toggle extends React.Component {

   constructor(props)
    {
   //子类 必须 在 constructor( )调用 super( )方法,否则新建实例时会报错。
   // 报错的原因是:子类是没有自己的 this 对象的,它只能继承自父类的 this 对象,然后对其进行加工,而super( )就是将父类中的this对象继承给子类的。没有 super,子类就得不到 this 对象。
   //无论有没有constructor,在render中this.props都是可以使用的,这是React自动附带的; 
      super(props);
      this.state = {isToggleOn: true};
// 这种绑定是使`this`在回调中起作用所必需的
      this.handleClick = this.handleClick.bind(this);  
   }

   handleClick() {    
       this.setState(state => ({ isToggleOn: !state.isToggleOn }));
    }

   render() {
       return (
            <button onClick={this.handleClick}> {this.state.isToggleOn ? 'ON' : 'OFF'}
           </button>
        );
    }

}
    
ReactDOM.render(
      <Toggle />,
      document.getElementById('root')
);

5.React 条件渲染 && React 列表 & Keys

条件

function Greeting(props) {
const isLoggedIn = props.isLoggedIn;
if (isLoggedIn) {
return <UserGreeting />;
}
return <GuestGreeting />;
}
 ReactDOM.render(
// Try changing to isLoggedIn={true}:
<Greeting isLoggedIn={false} />,
document.getElementById('root')
);

列表

function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
<li>{number}</li>
);
return (
<ul>{listItems}</ul>
);
}

const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
<NumberList numbers={numbers} />,
document.getElementById('root')
);

6. Hook( 挂钩 )&& React State(状态)

简介

Hook 是React 16.8中的新增功能。它们使您无需编写类即可使用 State 和其他React功能。
import React, { useState } from 'react';

function Example() {
  // Declare a new state variable, which we'll call "count"  const [count, setCount] = useState(0);
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

Hooks 钩子 解决了React在我们看来的各种的问题。无论您是学习React,每天使用它,还是偏爱具有相似组件模型的其他库,您都可能会意识到以下的一些问题。

  • 很难在组件之间重用状态逻辑
  • 复杂的组件变得难以理解
  • 类会使人和机器混淆
    至关重要的是,Hooks与现有代码并存,因此您可以逐渐采用它们。

如果想探索更多Hook的动机,可以详细参考(RFC)

钩子一览

建立自己的挂钩

有时,我们想在组件之间重用一些状态逻辑。传统上,有两种流行的解决方案:Higher-Order Components 和 Render Props。使用自定义钩子可以执行此操作,但无需在树中添加更多组件
import React, { useState, useEffect } from 'react';

function useFriendStatus(friendID) { 
const [isOnline, setIsOnline] = useState(null);
function handleStatusChange(status) {
    setIsOnline(status.isOnline);
  }

  useEffect(() => {
    ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
    };
  });

  return isOnline;
}
// 它friendID 作为参数,并返回我们的朋友是否在线。现在我们可以在两个组件中使用它:
//
function FriendStatus(props) {
  const isOnline = useFriendStatus(props.friend.id);
  if (isOnline === null) {
    return 'Loading...';
  }
  return isOnline ? 'Online' : 'Offline';
}
//
function FriendListItem(props) {
  const isOnline = useFriendStatus(props.friend.id);
  return (
    <li style={{ color: isOnline ? 'green' : 'black' }}>
      {props.friend.name}
    </li>
  );
}

这些组件的状态是完全独立的。挂钩是重用有状态逻辑而不是状态本身的一种方法。实际上,每个对Hook的调用都具有完全隔离的状态-因此,您甚至可以在一个组件中使用同一自定义Hook两次。

自定义钩子更多的是约定俗成的功能。如果函数的名称以“ use” 开头并且调用了其他挂钩,则我们将其称为自定义挂钩。该useSomething命名约定是我们的棉短绒插件如何能够找到使用钩在代码中的bug。

您可以编写自定义的Hook,这些自定义的Hook涵盖了各种用例,例如表单处理,动画,声明式订阅,计时器,以及可能还没有考虑的更多用例。

State Hook
import React, { useState } from 'react';

function Example() {
  // Declare a new state variable, which we'll call "count"  
const [count, setCount] = useState(0);
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}
// 等效类的示例
class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  render() {
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Click me
        </button>
      </div>
    );
  }
}
Effect Hook

如果你熟悉阵营类生命周期方法,你能想到的useEffect钩。因为componentDidMount,componentDidUpdate和componentWillUnmount结合。
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);

  // Similar to componentDidMount and componentDidUpdate:  
useEffect(() => {  
// Update the document title using the browser API 
 document.title = `You clicked ${count} times`;  });
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}
钩子规则:挂钩是JavaScript函数,但是它们施加了两个附加规则
  • 仅在顶层调用Hooks。

不要在循环,条件或嵌套函数中调用Hook。请始终在您的React函数的顶层使用挂钩。通过遵循此规则,可以确保每次渲染组件时都以相同的顺序调用Hook。

  • 仅从React函数组件调用Hook 。

不要从常规的JavaScript函数中调用Hook。React从React函数组件中调用Hook。可以从自定义挂钩中调用挂钩 。

我们提供了一个linter插件来自动执行这些规则。我们知道这些规则乍看起来似乎是局限性的或令人困惑的,但是它们对于使Hooks正常工作至关重要。

Hooks API参考

常用

posted @ 2020-05-07 19:05  徐锅  阅读(280)  评论(0编辑  收藏  举报