码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 【实战】 七、Hook,路由,与 URL 状态管理(下) —— React17+React Hook+TS4 最佳实践,仿 Jira 企业级项目(十三)


    文章目录

      • 一、项目起航:项目初始化与配置
      • 二、React 与 Hook 应用:实现项目列表
      • 三、TS 应用:JS神助攻 - 强类型
      • 四、JWT、用户认证与异步请求
      • 五、CSS 其实很简单 - 用 CSS-in-JS 添加样式
      • 六、用户体验优化 - 加载中和错误状态处理
      • 七、Hook,路由,与 URL 状态管理
        • 1+2.
        • 3~6
        • 7.完成URL状态管理与JS中的 iterator讲解


    学习内容来源:React + React Hook + TS 最佳实践-慕课网


    相对原教程,我在学习开始时(2023.03)采用的是当前最新版本:

    项版本
    react & react-dom^18.2.0
    react-router & react-router-dom^6.11.2
    antd^4.24.8
    @commitlint/cli & @commitlint/config-conventional^17.4.4
    eslint-config-prettier^8.6.0
    husky^8.0.3
    lint-staged^13.1.2
    prettier2.8.4
    json-server0.17.2
    craco-less^2.0.0
    @craco/craco^7.1.0
    qs^6.11.0
    dayjs^1.11.7
    react-helmet^6.1.0
    @types/react-helmet^6.1.6
    react-query^6.1.0
    @welldone-software/why-did-you-render^7.0.1
    @emotion/react & @emotion/styled^11.10.6

    具体配置、操作和内容会有差异,“坑”也会有所不同。。。


    一、项目起航:项目初始化与配置

    • 一、项目起航:项目初始化与配置

    二、React 与 Hook 应用:实现项目列表

    • 二、React 与 Hook 应用:实现项目列表

    三、TS 应用:JS神助攻 - 强类型

    • 三、 TS 应用:JS神助攻 - 强类型

    四、JWT、用户认证与异步请求

    • 四、 JWT、用户认证与异步请求(上)

    • 四、 JWT、用户认证与异步请求(下)

    五、CSS 其实很简单 - 用 CSS-in-JS 添加样式

    • 五、CSS 其实很简单 - 用 CSS-in-JS 添加样式(上)

    • 五、CSS 其实很简单 - 用 CSS-in-JS 添加样式(下)

    六、用户体验优化 - 加载中和错误状态处理

    • 六、用户体验优化 - 加载中和错误状态处理(上)

    • 六、用户体验优化 - 加载中和错误状态处理(中)

    • 六、用户体验优化 - 加载中和错误状态处理(下)

    七、Hook,路由,与 URL 状态管理

    1+2.

    • 七、Hook,路由,与 URL 状态管理(上)

    3~6

    • 七、Hook,路由,与 URL 状态管理(中)

    7.完成URL状态管理与JS中的 iterator讲解

    searchParams 拿到了, 接下来用暴露出来的 setSearchParams 来替换 ProjectList 里的 setParam

    修改 src\screens\ProjectList\index.tsx:

    ...
    export const ProjectList = () => {
      const [param, setParam] = useUrlQueryParam(["name", "personId"]);
      ...
    };
    ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    但是这样使用 setParam 时若是传入一个 { name1: 'Jack' } 的参数,没有任何报错拦截,这样肯定是不行的,所以需要在 setParam 即 setSearchParams 中使用对 key 的判断

    修改 src\utils\url.ts :

    import { useMemo } from "react";
    import { URLSearchParamsInit, useSearchParams } from "react-router-dom";
    import { cleanObject } from "utils";
    ...
    export const useUrlQueryParam = <K extends string>(keys: K[]) => {
      const [searchParams, setSearchParams] = useSearchParams();
      return [
        useMemo(
          () => keys.reduce((prev, key) => {
            // searchParams.get 可能会返回 null,需要预设值来兼容
            return { ...prev, [key]: searchParams.get(key) || "" };
            // 初始值会对类型造成影响,需要手动指定
          }, {} as { [key in K]: string }),
          // eslint-disable-next-line react-hooks/exhaustive-deps
          [searchParams]
        ),
        (params: Partial<{ [key in K]: unknown }>) => {
          const o = cleanObject({ ...Object.fromEntries(searchParams), ...params }) as URLSearchParamsInit
          return setSearchParams(o)
        },
      ] as const;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 遇到类似下面这样的类型不匹配问题,可以直接使用 as 来强制指定为提示的类型
      • 类型“{ [x: string]: unknown; }”的参数不能赋给类型“URLSearchParamsInit | ((prev: URLSearchParams) => URLSearchParamsInit) | undefined”的参数。

    通过 Object.fromEntries 引出 Iterator 的概念:

    Symbol.iterator 为每一个对象定义了默认的迭代器。该迭代器可以被 for...of 循环使用。

    Symbol.iterator - JavaScript | MDN

    在浏览器的 console 中做个小实验:

    • 定义一个数组并使用 for..of 遍历
    let arr = [1, 2, 3]
    for(v of arr) { console.log(v) }
    // 1
    // 2
    // 3
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 通过 Symbol.iterator 属性查看 此数组的 遍历器
    arr[Symbol.iterator]
    // ƒ values() { [native code] }
    
    • 1
    • 2
    • 将其执行结果拿出来
    let i = a[Symbol.iterator]()
    i
    // Array Iterator {}
    //  [[Prototype]]: Array Iterator
    //    next: ƒ next()
    //    Symbol(Symbol.toStringTag): "Array Iterator"
    //    [[Prototype]]: Object
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 可以看到它有个 next() 方法,执行一下
    i.next()
    // {value: 1, done: false}
    i.next()
    // {value: 2, done: false}
    i.next()
    // {value: 3, done: false}
    i.next()
    // {value: undefined, done: true}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 接下来实现一下自定义遍历器
    const obj = {
      data: ["hello", "world"],
      [Symbol.iterator]() {
        const self = this;
        let index = 0;
        return {
          next() {
            if (index < self.data.length) {
              return {
                value: self.data[index++] + "!",
                done: false
              };
            } else {
              return { value: undefined, done: true };
            }
          }
        };
      }
    };
    
    for (let o of obj) {
      console.log(o);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    线上地址:https://codesandbox.io/s/upbeat-wood-bum3j

    回归项目代码,searchParams 是 URLSearchParams 类型,通过以下代码可以看出使用 Object.fromEntries 可以将其(entries)转为 object

    new URLSearchParams({name: 'Jack'})[Symbol.iterator]
    // ƒ entries() { [native code] }
    
    • 1
    • 2

    代码逻辑明白了,接下来看下页面效果:

    • http://localhost:3000/projects?name=骑手&personId=18 直接访问,参数在页面中保持
    • 在页面中修改参数,URL 中同时更改,但有个小问题,下拉选择负责人时,页面中展示的是 personId,接下来解决一下

    在 src\screens\ProjectList\index.tsx 中打印 param

    在 src\screens\ProjectList\components\SearchPanel.tsx 中打印 users

    运行代码可以发现,param 中 id 是 string 但 users 中是 number,没有很好兼容,暂时在src\screens\ProjectList\components\SearchPanel.tsx 中将 id 强制转换为 string(String(user.id)):

    ...
    export const SearchPanel = ({ users, param, setParam }: SearchPanelProps) => {
      return (
        <Form css={{ marginBottom: "2rem", ">*": "" }} layout="inline">
          ...
          <Form.Item>
            <Select {...}>
              <Select.Option value="">负责人</Select.Option>
              {users.map((user) => (
                <Select.Option key={user.id} value={String(user.id)}>...</Select.Option>
              ))}
            </Select>
          </Form.Item>
        </Form>
      );
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    查看页面效果,功能正常啦!


    部分引用笔记还在草稿阶段,敬请期待。。。

  • 相关阅读:
    vantajs使用
    Lumiprobe 自由基分析丨H2DCFDA说明书
    网页数据抓取:融合BeautifulSoup和Scrapy的高级爬虫技术
    后端SpringBoot+前端Vue前后端分离的项目(二)
    mySql语句整理
    RIP动态路由协议详解
    MYSQL--JDBC优化
    ubuntu 22.04配置静态ip
    FX2TRT
    Maven实战—搭建微服务 Maven 工程架构
  • 原文地址:https://blog.csdn.net/qq_32682301/article/details/131813894
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号