19、React后端交互、状态管理及React 18新特性全解析

React后端交互、状态管理及React 18新特性全解析

1 React与后端服务交互

1.1 后端认证

可以使用Firebase构建更复杂的验证和安全规则,还能实现忘记密码选项以及不同的认证方式,如使用Google、Facebook登录等。此外,还有许多后端服务可用于实现认证,如Auth0。

1.2 HTTP请求

API是两个应用程序相互通信的连接,能实现应用程序前后端之间的通信。在React中,可以使用Axios库从浏览器创建HTTP请求。

以下是一个示例,创建一个允许输入员工姓名和角色的应用程序:
1. 安装依赖:

npm install axios date-fns
  1. 创建 App.js 文件:
import "./styles.css";
import axios from "axios";
import { useState } from "react";
import { format, parseISO } from "date-fns";

const fieldStyle = {
  marginTop: "20px",
  float: "left",
  width: "70%",
  fontSize: 20
};

const buttonStyle = {
  marginTop: "20px",
  backgroundColor: "lightBlue",
  width: "30%",
  fontSize: 20,
  cursor: "pointer",
  marginRight: "20px"
};

function App() {
  const [name, setName] = useState("");
  const [role, setRole] = useState("");
  const [display, setDisplay] = useState("");

  const submit = () => {
    axios
     .post(`https://reqres.in/api/users`, { name: name, job: role })
     .then((res) => {
        setDisplay(
          `${name} is appointed as ${role} on ${format(
            parseISO(res.data.createdAt),
            "dd-MMM-yyyy"
          )} with ID ${res.data.id}`
        );
        console.log(res.data);
      });
  };

  const getManagerName = () => {
    axios.get(`https://reqres.in/api/users/2`).then((res) => {
      console.log(res.data);
      setDisplay(
        `${res.data.data.first_name} is the manager. The contact  email 
is  ${res.data.data.email}.`
      );
    });
  };

  return (
    <div style={{ width: "100%" }}>
      <input
        placeholder="Name"
        value={name}
        style={fieldStyle}
        onChange={(e) => setName(e.target.value)}
      />
      <input
        placeholder="Role"
        value={role}
        style={fieldStyle}
        onChange={(e) => setRole(e.target.value)}
      />
      <button style={buttonStyle} onClick={submit}>
        Submit
      </button>
      <button style={buttonStyle} onClick={getManagerName}>
        Get Manager name
      </button>
      <br />
      {display && <label style={fieldStyle}> {display}</label>}
    </div>
  );
}

export default App;

该应用创建了一个包含姓名和角色输入框的表单,点击“Submit”按钮会发送POST请求创建用户并显示相关信息,点击“Get Manager name”按钮会发送GET请求获取经理信息并显示。

1.3 Redux状态管理

Redux是用于前端应用程序状态管理的库,可与任何其他库或框架一起使用。Redux的核心概念包括:
- Store :保存应用的全局状态。
- Action :访问store的入口,包含type和payload属性。
- Reducer :接收当前状态和action,根据action改变状态并返回新状态。
- Dispatch :Redux store的方法,携带action对象来更新状态。

以下是一个使用Redux的待办事项应用示例:
1. 安装依赖:

npm install redux redux-react
  1. 创建 index.js 文件:
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import App from "./App";
import { createStore } from "redux";
import { Provider } from "react-redux";

const reducer = (state = [{ name: "Meeting at 9" }], action) => {
  switch (action.type) {
    case "addNewTask":
      return [...state, action.payload];
    default:
      return state;
  }
};

const store = createStore(reducer);
const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

root.render(
  <StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </StrictMode>
);
  1. 创建 App.js 文件:
import { useState } from "react";
import { connect } from "react-redux";

function App(props) {
  const [task, setTask] = useState("");

  const handleClick = () => {
    props.dispatch({
      type: "addNewTask",
      payload: { name: task }
    });
    setTask("");
  };

  return (
    <>
      <h2> Add tasks </h2>
      <input
        type="text"
        value={task}
        onChange={(e) => setTask(e.target.value)}
      />
      <br />
      <br />
      <button onClick={(e) => handleClick(e)}>
        Add
      </button>
      <hr />
      <h2>To Do List </h2>
      <ul>
        {props.tasks.map((task) => (
          <li key={task.name}>{task.name}</li>
        ))}
      </ul>
    </>
  );
}

const mapStateToProps = (state) => {
  return { tasks: state };
};

export default connect(mapStateToProps)(App);

该应用创建了一个待办事项列表,用户可以输入新任务并添加到列表中。

2 React 18新特性

2.1 新的Root API和渲染方式

在React 18中,渲染根组件的方式发生了变化。以下是一个示例对比:
- React 17的 index.js

import { StrictMode } from "react";
import ReactDOM from "react-dom";
import App from "./App";

const rootElement = document.getElementById("root");
ReactDOM.render(
  <StrictMode>
    <App />
  </StrictMode>,
  rootElement
);
  • React 18的 index.js
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import App from "./App";

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);
root.render(
  <StrictMode>
    <App />
  </StrictMode>
);

新的Root API使用 ReactDOM.createRoot 代替了 ReactDOM.render ,并且不再需要将根元素传递给 render 方法,同时提供了对React 18并发特性的访问。

2.2 React并发执行

从React 18开始,并发将成为React的特性。通过升级到React 18和新的Root API,可以使用React的并发特性。

以去餐厅吃饭并完成工作为例,有两种选择:
- 选项1:先吃完饭回家再完成工作,可能会延迟睡觉时间。
- 选项2:点餐等待时开始工作,若食物先准备好则暂停工作,回家后继续完成,可节省时间并提前睡觉。

在React中,之前一旦事务开始就无法中断,而React 18引入了并发特性,提高了应用程序的性能。

2.3 总结

本文介绍了React与后端服务的交互,包括使用Firebase进行认证、使用Axios进行HTTP请求以及使用Redux进行状态管理。同时,还介绍了React 18的新特性,如新的Root API和渲染方式、并发执行等。这些知识将帮助你更好地开发React应用程序,并为升级现有项目做好准备。

以下是一个简单的流程图,展示了Redux的工作流程:

graph LR
    A[Component] -->|Dispatch Action| B[Store]
    B -->|Reducer| C[New State]
    C -->|Update| A

表格总结Redux核心概念:
| 概念 | 描述 |
| ---- | ---- |
| Store | 保存应用全局状态 |
| Action | 访问store的入口,含type和payload |
| Reducer | 根据action改变状态并返回新状态 |
| Dispatch | 携带action对象更新状态 |

2.4 并发特性之过渡(Transition)

在 React 18 的并发特性中,过渡(Transition)是一个重要的概念。过渡允许我们将某些状态更新标记为不太紧急的操作,这样 React 就可以在不影响紧急更新的情况下,更灵活地安排这些操作的执行时间。

例如,当用户在搜索框中输入关键词时,搜索结果的更新可能不是立即需要的,而输入框的响应性则是更重要的。我们可以将搜索结果的更新标记为过渡更新,让 React 在有空闲时间时再进行处理。

以下是一个简单的示例代码:

import { useState, useTransition } from 'react';

function SearchApp() {
  const [isPending, startTransition] = useTransition();
  const [inputValue, setInputValue] = useState('');
  const [searchResults, setSearchResults] = useState([]);

  const handleInputChange = (e) => {
    const value = e.target.value;
    setInputValue(value);
    startTransition(() => {
      // 模拟搜索操作
      const results = performSearch(value);
      setSearchResults(results);
    });
  };

  function performSearch(query) {
    // 这里可以是实际的搜索逻辑
    return ['Result 1', 'Result 2'];
  }

  return (
    <div>
      <input
        type="text"
        value={inputValue}
        onChange={handleInputChange}
        placeholder="Search..."
      />
      {isPending ? (
        <p>Searching...</p>
      ) : (
        <ul>
          {searchResults.map((result, index) => (
            <li key={index}>{result}</li>
          ))}
        </ul>
      )}
    </div>
  );
}

export default SearchApp;

在这个示例中, useTransition 钩子返回一个 isPending 状态和一个 startTransition 函数。当调用 startTransition 时,其中的状态更新将被标记为过渡更新。在过渡更新进行时, isPending 会变为 true ,我们可以利用这个状态来显示加载提示。

2.5 并发特性之流式服务器端渲染(Streaming SSR)

流式服务器端渲染(Streaming SSR)是 React 18 并发特性的另一个重要应用。传统的服务器端渲染会在整个页面渲染完成后才将 HTML 发送给客户端,而流式服务器端渲染允许 React 在服务器上逐步生成 HTML 并发送给客户端,这样客户端可以更快地开始显示页面内容。

以下是一个简单的流程图,展示了流式服务器端渲染的过程:

graph LR
    A[Server] -->|Stream HTML| B[Client]
    A -->|Generate More HTML| A
    B -->|Start Rendering| B

在实际应用中,要实现流式服务器端渲染,我们需要使用 React 的 renderToPipeableStream 方法。以下是一个简单的示例:

import React from 'react';
import { renderToPipeableStream } from 'react-dom/server';
import App from './App';

function handleRequest(req, res) {
  const { pipe } = renderToPipeableStream(<App />, {
    onShellReady() {
      res.statusCode = 200;
      res.setHeader('Content-Type', 'text/html');
      pipe(res);
    },
    onAllReady() {
      // 所有内容都准备好后的处理
    },
    onError(err) {
      res.statusCode = 500;
      res.end('Error occurred');
    },
  });
}

// 这里可以是服务器的启动代码

在这个示例中, renderToPipeableStream 会将 React 组件渲染为一个可管道化的流。当外壳(shell)准备好时,就可以将其发送给客户端,客户端可以开始渲染页面的基本结构。随着更多内容的生成,服务器会继续将其发送给客户端。

2.6 自动批处理(Automatic Batching)

React 18 还引入了自动批处理的特性。在之前的版本中,只有在 React 事件处理函数中进行的状态更新才会被批处理,而在异步操作(如 setTimeout Promise 等)中的状态更新不会被批处理。在 React 18 中,无论状态更新是在什么地方进行的,都会被自动批处理,这可以减少不必要的重新渲染,提高性能。

以下是一个示例代码来说明自动批处理的效果:

import { useState } from 'react';

function App() {
  const [count1, setCount1] = useState(0);
  const [count2, setCount2] = useState(0);

  const handleClick = () => {
    setTimeout(() => {
      setCount1((prev) => prev + 1);
      setCount2((prev) => prev + 1);
      // 在 React 18 中,这两个状态更新会被批处理
    }, 0);
  };

  return (
    <div>
      <p>Count 1: {count1}</p>
      <p>Count 2: {count2}</p>
      <button onClick={handleClick}>Update Counts</button>
    </div>
  );
}

export default App;

在这个示例中,即使状态更新是在 setTimeout 中进行的,React 18 也会将它们批处理,只进行一次重新渲染。

2.7 更新后的严格模式(Strict Mode)

React 18 对严格模式进行了更新。严格模式是 React 提供的一种开发工具,用于在开发环境中帮助我们发现潜在的问题。在 React 18 中,严格模式会额外调用一些生命周期函数和副作用函数,以确保组件在多次挂载和卸载时的行为是一致的。

例如,在严格模式下, useEffect 钩子的清理函数会在组件卸载时被调用,并且在重新挂载时, useEffect 会再次执行,这有助于我们发现一些可能的内存泄漏或副作用处理不当的问题。

2.8 新的钩子(Hooks)

React 18 还引入了一些新的钩子,如 useId useSyncExternalStore 等。

  • useId :用于生成唯一的 ID,在需要为组件生成唯一标识符的场景中非常有用,例如在表单元素的 id 属性中使用。
import { useId } from 'react';

function Form() {
  const inputId = useId();
  return (
    <form>
      <label htmlFor={inputId}>Name:</label>
      <input type="text" id={inputId} />
    </form>
  );
}
  • useSyncExternalStore :用于订阅外部数据源,并且在数据发生变化时更新组件。这对于与第三方库或外部状态管理系统集成非常有用。

2.9 总结

React 18 带来了许多令人兴奋的新特性,包括并发特性、新的 Root API、自动批处理、更新后的严格模式和新的钩子等。这些特性不仅提高了应用程序的性能和响应性,还为开发者提供了更多的工具和灵活性。通过学习和应用这些新特性,我们可以构建出更加高效、稳定和用户体验良好的 React 应用程序。

表格总结 React 18 新特性:
| 特性 | 描述 |
| ---- | ---- |
| 新的 Root API | 使用 ReactDOM.createRoot 代替 ReactDOM.render ,提供并发特性访问 |
| 并发特性 | 包括过渡和流式服务器端渲染,提高性能和响应性 |
| 自动批处理 | 无论状态更新位置,都会自动批处理,减少重新渲染 |
| 更新后的严格模式 | 额外调用生命周期和副作用函数,发现潜在问题 |
| 新的钩子 | 如 useId useSyncExternalStore 等,提供更多功能 |

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值