react基础语法的一些注意事项和边界情况

1.组件名称必须以大写字母开头 React 会将以小写字母开头的组件视为原生 DOM 标签;

2.Props 的只读性,组件无论是使用函数声明还是通过 class 声明,都决不能修改自身的 props,React 组件都必须像纯函数一样保护它们的 props 不被更改

3.不要直接修改 State,构造函数是唯一可以给 this.state 赋值的地方,State 的更新可能是异步的,要解决这个问题,可以让 setState() 接收一个函数而不是一个对象;

4.数据是自上而下的,不管是父组件或是子组件都无法知道某个组件是有状态的还是无状态的;组件可以选择把它的 state 作为 props 向下传递到它的子组件中;

5.React 事件的命名采用小驼峰式(camelCase),而不是纯小写,使用 JSX 语法时你需要传入一个函数作为事件处理函数,而不是一个字符串

6.React 中另一个不同点是你不能通过返回 false 的方式阻止默认行为。你必须显式的使用 preventDefault;

7.一个好的经验法则是:在 map() 方法中的元素需要设置 key 属性;key 只是在兄弟节点之间必须唯一;

8.在 React 中,将多个组件中需要共享的 state 向上移动到它们的最近共同父组件中,便可实现共享 state。这就是所谓的“状态提升”。

9.不要在 render 方法中使用 HOC(高阶组件)会造成性能问题更为严重的是重新挂载组件会导致该组件及其所有子组件的状态丢失(Refs 在高阶组件不会被传递)

10.JavaScript 表达式作为 Props;if 语句以及 for 循环不是 JavaScript 表达式,所以不能在 JSX 中直接使用;

11.避免使用 refs 来做任何可以通过声明式实现来完成的事情;勿过度使用 Refs;

12.默认情况下,你不能在函数组件上使用 ref 属性,因为它们没有实例;果要在函数组件中使用 ref,你可以使用 forwardRef;或者可以将该组件转化为 class 组件,不管怎样,你可以在函数组件内部使用 ref 属性,只要它指向一个 DOM 元素或 class 组件;

13.避免将 props 的值复制给 state!这是一个常见的错误;

14.每个组件都可以获取到 props.children。它包含组件的开始标签和结束标签之间的内容;

摘自官方文档https://react.docschina.org/docs/getting-started.html

/*
 * @Description: 一些边界基础语法点
 * @Version: 2.0
 * @Autor: lhl
 * @Date: 2020-02-25 17:20:57
 * @LastEditors: lhl
 * @LastEditTime: 2020-04-20 14:51:57
 */
import React, { Component } from 'react'
import PropTypes from 'prop-types';
// import logo from './logo.svg';
import './App.css';
import {MyContext, themes} from './context/myContext'
// import axios from 'axios' // react 使用 axios
// import AntdTest from './page/AntdTest'
// import ReactRouterTest from './page/ReactRouterTest';

// 懒加载组件  React.lazy 和 Suspense 技术还不支持服务端渲染。如果你想要在使用服务端渲染的应用中使用,官方推荐 Loadable Components 这个库
// 实现组件代码分割,路由的代码分割
// import React, { Suspense } from 'react';
// const ReactRouterTest = React.lazy(() => import('./ReactRouterTest'));

// 实现组件代码分割
{/* <Suspense fallback={<div>Loading...</div>}>
  <section>
    <ReactRouterTest />
  </section>
</Suspense> */}

// 路由的代码分割
{/* <Router>
    <Suspense fallback={<div>Loading...</div>}>
      <Switch>
        <Route exact path="/" component={Home}/>
      </Switch>
    </Suspense>
</Router> */}

// 本页面只做基础的 react 常用语法糖   react-window 和 react-virtualized 是热门的虚拟滚动库
// 一般选用受控组件 来处理表单数据。在一个受控组件中,表单数据是由 React 组件来管理的。另一种替代方案是使用非受控组件,这时表单数据将交由 DOM 节点来处理;
export default class App extends Component {
  constructor(props, context) {
    super(props, context);
    this.state = {
      theme: themes.light,
    }
    this.inpt =  React.createRef()
  }
  
  // 建议在componentDidMount函数里作ajax请求
  componentDidMount() {
    // 更改title
    document.title = '首页'

    // 访问 Refs
    console.log(this.inpt.current,'ref')
    this.inpt.current.focus();
  }

  // 渲染函数 
  render() {
    console.log('render---组件挂载中---2')
    return (
      <div className="wrap-box">
        <input type="text" ref={this.inpt} />
        <MyContext.Provider value={this.state.theme}>
          <Toolbar />
        </MyContext.Provider>
        <div dangerouslySetInnerHTML={createMarkup()} />
      </div>
    )
  }
}

// dangerouslySetInnerHTML 是 React 为浏览器 DOM 提供 innerHTML 的替换方案 容易无意中使用户暴露于跨站脚本(XSS)的攻击
function createMarkup() {
  return {__html: 'First &middot; Second'};
}

// 中间的组件再也不必指明往下传递 theme 了。
function Toolbar() {
  return (
    <div>
      <ThemeButton />
      {/* false, null, undefined, and true 是合法的子元素。但它们并不会被渲染 布尔类型、Null 以及 Undefined 将会忽略 */}
      <div />
      <div></div>
      <div>{false}</div>
      <div>{null}</div>
      <div>{undefined}</div>
      <div>{true}</div>
    </div>
  );
}

{/* 结果: <button theme="red" type="button" class="ant-btn ant-btn-primary"><span>Primary</span></button> */}
class ThemeButton extends React.Component {
  // 指定 contextType 读取当前的 theme context。
  // React 会往上找到最近的 theme Provider,然后使用它的值。
  // 在这个例子中,当前的 theme 值为 “dark”。
  static contextType = MyContext;
  render() {
    let value = this.context;
    console.log(value,'value')
    // 默认 Prop 值 使用 PropTypes 进行类型检查
    console.log(this.props.name,'this.props.name')
    return <button theme={value.background} type="primary"  style={{backgroundColor: value.background}}>Primary</button>;
  }
}

// 指定 props 的默认值: 校验传参的类型
ThemeButton.propTypes = {
  name: PropTypes.string
};

ThemeButton.defaultProps = {
  name: 'test'
};
/*
 * @Description: react Context
 * @Version: 2.0
 * @Autor: lhl
 * @Date: 2020-04-20 11:15:46
 * @LastEditors: lhl
 * @LastEditTime: 2020-04-20 11:42:28
 */
// API Context 设计目的是为了共享那些对于一个组件树而言是“全局”的数据
// 1.React.createContext
// 2.Context.Provider
// 3.Class.contextType
// 4.Context.Consumer
// 5.Context.displayName
import React from 'react'

export const themes = {
  light: {
    foreground: '#000000',
    background: 'red',
  },
  dark: {
    foreground: '#333',
    background: '#333',
  },
};

export const MyContext = React.createContext(
  themes.dark // 默认值
);
原文地址:https://www.cnblogs.com/lhl66/p/12737802.html