ReactTraining

这个仓库是一个 React 入门教学项目,当前分支对应的实际代码基线是 React 16.14.0。

当前版本:React 16.14.0
当前演示方式:原生 HTML + JSX + Babel + CDN 引入
适用场景:学习 React 基础概念、组件化开发、状态管理和生命周期

仓库目录说明

  • 00-introduce:介绍 React 的背景和应用场景
  • 01-developmentEnvironment:开发环境和 Hello React 示例
  • 02-JSX:JSX 语法与渲染基础
  • 03-component:组件基础与组合
  • 04-props:props 传值与默认值
  • 05-state:state 和事件处理
  • 06-lifecycle:组件生命周期
  • 07-ajax:Ajax / JSONP 请求示例
  • 08-ECMAScript6:ES6 语法回顾
  • 09-hooks:React Hooks 入门与进阶示例(useState / useEffect / useRef / useCallback / 自定义 Hook / 表单、组合、数据请求和本地存储实战)

当前项目的真实依赖版本

从仓库中的示例代码来看,实际使用的是:

  • React 16.14.0
  • ReactDOM 16.14.0
  • Babel Standalone 7.23.2

所有 demo 都是通过 CDN 引入:

<script src="https://cdn.jsdelivr.net/npm/react@16.14.0/umd/react.production.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/react-dom@16.14.0/umd/react-dom.production.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@babel/standalone@7.23.2/babel.min.js"></script>

运行方式

1. 直接打开 HTML 文件

在浏览器中直接双击打开任意章节页面即可。

2. 本地服务器方式

在项目根目录执行:

python -m http.server 8000

然后在浏览器中访问:

http://localhost:8000/

基础结构示例

当前项目中的每个 demo 基本使用下面的结构:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Title</title>
  </head>
  <body>
    <div id="example"></div>

    <script src="https://cdn.jsdelivr.net/npm/react@16.14.0/umd/react.production.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/react-dom@16.14.0/umd/react-dom.production.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@babel/standalone@7.23.2/babel.min.js"></script>

    <script type="text/babel">
      ReactDOM.render(<h1>Hello, React!</h1>, document.getElementById("example"));
    </script>
  </body>
</html>

说明:

  • React 用于定义组件和虚拟 DOM
  • ReactDOM 用于挂载到真实 DOM
  • Babel 用于编译 JSX 语法

JSX 语法

当前代码大量使用 JSX:

<script type="text/babel">
  const name = "React";

  ReactDOM.render(
    <h1>Hello, {name}!</h1>,
    document.getElementById("example")
  );
</script>

常见规范:

  • 使用 {} 插入表达式
  • 使用 className 替代 class
  • 使用 htmlFor 替代 for
  • 返回值通常只能有一个根节点

组件开发

当前仓库中的组件部分已经从旧版的 React.createClass 语法逐步过渡到更符合 React 16 的类组件写法:

<script type="text/babel">
  class HelloWorld extends React.Component {
    render() {
      return <h1>Hello world!</h1>;
    }
  }

  ReactDOM.render(<HelloWorld />, document.getElementById("example"));
</script>

props 与 state

本仓库涵盖了以下核心内容:

  • props:组件参数传递
  • state:组件内部状态
  • 事件绑定:点击、输入等交互
  • setState:状态更新
  • 生命周期:挂载、更新、卸载

例如:

<script type="text/babel">
  class CheckBox extends React.Component {
    constructor(props) {
      super(props);
      this.state = { isCheck: false };
    }

    click = () => {
      this.setState({ isCheck: !this.state.isCheck });
    };

    render() {
      return (
        <div>
          <input type="checkbox" onClick={this.click} />
          <span>{this.state.isCheck ? "true" : "false"}</span>
        </div>
      );
    }
  }

  ReactDOM.render(<CheckBox />, document.getElementById("example"));
</script>

生命周期

生命周期章节是项目中非常重要的一部分,示例中已经使用了 ES6 Class 组件:

<script type="text/babel">
  class Demo extends React.Component {
    static defaultProps = {
      name: "world",
    };

    constructor(props) {
      super(props);
      this.state = {
        isSelect: false,
      };
    }

    render() {
      return <h1>Hello, {this.props.name}!</h1>;
    }
  }
</script>

包含的生命周期知识包括:

  • componentDidMount
  • shouldComponentUpdate
  • componentDidUpdate
  • componentWillUnmount

Ajax 示例

项目中的 Ajax 章节演示了如何通过 jQuery 的 $.ajax 发送 JSONP 请求,并将返回数据渲染到组件中。

这部分内容用于帮助学习:

  • React 组件挂载后获取数据
  • this.setState(...) 更新视图
  • 异步数据加载与渲染

Hook 入门(核心内容已齐全)

React 16.8 引入了 Hook,允许在函数组件中使用状态和副作用,让组件更加轻量、复用性更强。当前分支使用的是 React 16.14.0,因此它完全支持 Hook 语法。

对于这个入门级仓库来说,Hook 的核心知识点已经基本介绍完整,足够帮助学习者从类组件过渡到现代 React 函数组件开发。

Hook 的核心价值

  • 让函数组件也可以拥有状态
  • 让副作用逻辑更清晰
  • 让组件逻辑更容易复用
  • 更符合现代 React 项目的写法

1. useState:状态管理

<script type="text/babel">
  const { useState } = React;

  function Counter() {
    const [count, setCount] = useState(0);

    return (
      <button onClick={() => setCount(count + 1)}>
        当前计数:{count}
      </button>
    );
  }

  ReactDOM.render(<Counter />, document.getElementById("example"));
</script>

2. useEffect:副作用与生命周期替代

<script type="text/babel">
  const { useState, useEffect } = React;

  function Timer() {
    const [time, setTime] = useState(new Date().toLocaleTimeString());

    useEffect(() => {
      const timer = setInterval(() => {
        setTime(new Date().toLocaleTimeString());
      }, 1000);

      return () => clearInterval(timer);
    }, []);

    return <h2>{time}</h2>;
  }

  ReactDOM.render(<Timer />, document.getElementById("example"));
</script>

3. useRef:访问 DOM 或保存引用

<script type="text/babel">
  const { useRef } = React;

  function Demo() {
    const inputRef = useRef(null);

    return (
      <div>
        <input ref={inputRef} />
        <button onClick={() => inputRef.current.focus()}>聚焦</button>
      </div>
    );
  }
</script>

4. useCallback:缓存函数

useCallback 主要用于避免不必要的函数重建,和 React.memo 配合时比较常见。

<script type="text/babel">
  const { useState, useCallback, memo } = React;

  const Child = memo(function Child({ onClick }) {
    return <button onClick={onClick}>点击我</button>;
  });

  function Parent() {
    const [count, setCount] = useState(0);

    const handleClick = useCallback(() => {
      setCount((prev) => prev + 1);
    }, []);

    return <Child onClick={handleClick} count={count} />;
  }
</script>

5. 自定义 Hook:逻辑复用

<script type="text/babel">
  const { useState, useEffect } = React;

  function useWindowSize() {
    const [size, setSize] = useState({
      width: window.innerWidth,
      height: window.innerHeight,
    });

    useEffect(() => {
      const handleResize = () => setSize({
        width: window.innerWidth,
        height: window.innerHeight,
      });

      window.addEventListener("resize", handleResize);
      return () => window.removeEventListener("resize", handleResize);
    }, []);

    return size;
  }
</script>

Hook 与类组件的对应关系

  • this.state / setState → useState
  • componentDidMount / componentDidUpdate / componentWillUnmount → useEffect
  • this.props → 函数组件直接接收参数
  • this.ref → useRef
  • 函数缓存 / 避免重复创建 → useCallback
  • 复用逻辑 → 自定义 Hook

9-hooks 目录中的示例

这部分已经覆盖了入门者最需要掌握的 Hook 内容:

这些示例已经足够支撑初学者理解 Hook 的核心思想。

可选扩展案例(非必需)

下面这些文件属于“扩展练习”,用于帮助更进一步理解 Hook 在真实项目中的使用场景:

这些内容可以作为后续练习,但不是本仓库必需的 Hook 基础知识。

在学习上,建议遵循这样的顺序:

  1. 先学 useState
  2. 再学 useEffect
  3. 再学 useRef
  4. 再理解 useCallback
  5. 最后掌握自定义 Hook

这样已经足够建立现代 React 的基础认知。


学习建议

如果你正在学习这个仓库,建议按顺序阅读:

  1. 01-developmentEnvironment
  2. 02-JSX
  3. 03-component
  4. 04-props
  5. 05-state
  6. 06-lifecycle
  7. 07-ajax
  8. 08-ECMAScript6
  9. 09-hooks

这样能更自然地理解 React 的基本工作方式、组件化思维,以及 Hook 的现代写法。


结论

本仓库当前代码的真实版本是 React 16.14.0,因此 README 应该与当前分支实现保持一致,而不是继续保留旧版 React 15.3.2 的说明。

这份仓库更适合初学者学习:

  • JSX 语法
  • React 组件基础
  • props 与 state
  • 生命周期
  • Ajax 数据交互
  • ES6 语法基础

如果你希望继续学习现代 React 工程化开发,后续可进一步接触:

  • Webpack / Vite
  • npm / yarn
  • React Router
  • 状态管理库
  • 组件库与工程化结构

参考链接

建议配合以下资料一起学习:

这个仓库的目标是帮助初学者先建立“组件思维”和“React 生命周期/状态管理”的基础认知,再逐步进入真实项目开发。