快来自查有没有让你懵的一些React组件化代码中的点!!

67 阅读3分钟

1. ES6重命名导入语法

import { BrowserRouter as Router } from "react-router-dom";

BrowserRouter是JavaScript中ES6的“重命名导入”语法,从react-router-dom这个包里导入BrowserRouter组件, 并且在当前文件里把它叫做Router。我们就可以直接在代码里用<Router>了。

详细请参考: MDN: import - JavaScript | MDN

2. 对象解构赋值

export const GlobalProvider = ({ children }) => {
const [state, dispatch] = useReducer(repoReducer, initalState);
};

这里的{children}与通常函数传值的参数children含义是不一样,这里是对象解构赋值{children}是从props中解构取出来的children属性,而如果直接children,此时children就是props。这样写就是为了代码更简洁,不用每次都写props.children。其实const [state, dispatch] = useReducer(repoReducer, initalState);也是解构赋值

官方文档和主流社区都推荐如下写法:

function MyComponent({ children }) {
  return <div>{children}</div>;
}

详细请参考: Passing Props to a Component - React 官方文档

3.路径别名(Path Alias)

import { Reducer } from "@/reducers/Reducer";

import { repoReducer } from "@/reducers/repoReducer";@不是JavaScript或React语法,而是路径别名,用来简化导入路径。一般来说,@代表项目的src目录,所以说@/reducers/Reducer等价于src/reducers/Reducer

如何在项目中配置 @ ?

不同构建工具配置方式不同。常见如下:

1.Vite项目中

import { defineConfig } from 'vite';
import path from 'path';
export default defineConfig({
  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src'),
    },
  },
});

2.webpack项目中

const path = require('path');
module.exports = {
  // ...其他配置
  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src'),
    },
  },
};

3.在TypeScript项目中

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    }
  }
}

4. React组件的JSX写法

如下路由伪代码,会疑惑也许会疑惑为什么fallback/element=后面是{< />}而不是{ }或者" "

import Loading from "./components/Loading";
return (
    <Suspense fallback={<Loading />}>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/users/:id/repos" element={<RepoList />} />
        <Route path="/users/:id/repos/:repoId" element={<RepoDetail />}></Route>
        <Route path="*" element={<NotFound />} />
      </Routes>
    </Suspense>
  );

<Loading />是React组件的JSX写法,<Loading />表示渲染一个Loading组件,它会显示Loading组件里定义的内容(比如一个加载动画),= {<Loading />}的意思是把一个React元素(组件实例)作为fallback/element的值传递给Suspense/Route

为什么不写成= " "= { }?

前置知识: Loading是组件类型,本质上是一个函数(或类),<Loading />是组件实例。形象理解就是,Loading就像是“模具”或“蓝图”,而<Loading/>是这个摸具生产出来的成品

  • = "Loading"只是一个字符串,React会直接渲染字符串“loading”,这样页面上只会显示文字loading,而不是自定义组件中的样式或动画。

  • = {Loading}传递的是组件本身(即函数或类),而不是组建的实例,React需要的是一个元素(即<Loading />),而不是组件类型,如果写fallback={Loading},React不会自动渲染它,页面不会显示你要的内容。

5.import{ xxx }还是import xxx ? export还是export default ?

工具函数/常量/模块(非组件)

推荐: import { xx } from "..." 大括号的写法,叫做命名导入(named input),只能导入模块中通过export命名导出的内容。语法:export const xxx = ...export function xxx(){}

因为一个工具文件可能会导出多个函数或变量。

例如自定义hook有多个函数:

import axios from "axios";
const BASE_URL = "https://api.github.com"; // 基础地址

export const getRepos = (username) => {
  return axios.get(`${BASE_URL}/users/${username}/repos`);
};

export const getRepoDetail = async (username, repoName) => {
  return await axios.get(`${BASE_URL}/repos/${username}/${repoName}`);
};

组件(React组件)

推荐: import from "..."无大括号的写法,叫做默认导入(default import),只能导入模块中通过export default导出的内容,语法:export default xxx

因为一个文件通常只导出一个主要组件,这样导入时更简洁。

例如Loading组件:

function Loading() {
  return <div>Loading...</div>;
}

export default Loading;

6.路由参数(: id

 <Route path="/users/:id/repos" element={<RepoList />} />
 <Route path="/users/:id/repos/:repoId" element={<RepoDetail />}></Route>

如上路由代码,:id其实是路由参数的语法,在React Router(以及很多前端路由库中),/users/:id/repos里的:id表示这是一个动态参数,不是固定的字符串,:id里的冒号:表示这是一个变量

如何获取:id的值?

import { useParams } from "react-router-dom";

function RepoList() {
  const { id } = useParams();
  // id 就是 URL 里的动态部分,比如 123
}

在对应的组件中,可以用React Router的hook来获取参数,这样,当URL为/users/123/repos/users/abc/repos时,React Router会自动把id=123/abc这个参数“注入”到响应使用useParam的组件内部。

注意: 路由参数不是通过props传递!

详细请参考资料:React Router - useParams