React18开发总结(完善中)

news2024/11/26 14:51:01

遇到这样一个问题,初始化时用户登陆后需要获取到用户信息,但是发现获取用户信息这个接口触发了2次,这是不应该的,于是我查阅了一下资料,把自己的笔记记录下来。 还有就是使用mobx遇到的控制台警告问题,也一并记录一下。

一.React18,useEffect被调用了两次

  1. import  { useState, useEffect } from "react";
    
    const Counter = () => {
      const [count, setCount] = useState(5);
    
      useEffect(() => {
        console.log("rendered");
        console.log(count);
      }, [count]);
    
      console.log("rendered");
    
      return (
        <div>
          <h1> Counter </h1>
          <div> {count} </div>
          <button onClick={() => setCount(count + 1)}> click to increase </button>
        </div>
      );
    };
    
    export default Counter;

可以用这段话来解释:

当你在strict mode in development时,这是一个来自React18本身的问题。基本上,即使在React18中卸载之后,核心团队仍在试图改变组件的状态。useEffect两次被调用与此功能有关。目前正在讨论如何解决这个问题。要了解更多信息,请观看YouTube视频。现在,您可以使用useRef使用布尔值ref来避免它,在您的例子中是这样的:

import  { useState, useEffect, useRef } from "react";

const Counter = () => {
  const firstRenderRef = useRef(true);
  const [count, setCount] = useState(5);

  useEffect(() => {
    if(firstRenderRef.current){
      firstRenderRef.current = false;
      return;
    }
    console.log("rendered");
    console.log(count);
  }, [count]);
console.log("rendered");
  return (
    <div>
      <h1> Counter </h1>
      <div> {count} </div>
      <button onClick={() => setCount( count + 1 )}> click to increase </button>
    </div>
  );
};

export default Counter;

其实还有一种做法就是不适用框架默认的严格模式,这样初始化数据的时候也只会走一次接口,我们看下react官网是怎么说的:

React 提供了 “严格模式”,在严格模式下开发时,它将会调用每个组件函数两次。通过重复调用组件函数,严格模式有助于找到违反这些规则的组件

...

严格模式在生产环境下不生效,因此它不会降低应用程序的速度。如需引入严格模式,你可以用 <React.StrictMode> 包裹根组件。一些框架会默认这样做。

2.[MobX] Since strict-mode is enabled, changing (observed) observable values without using an action..

报错源码展示:

import { makeAutoObservable,  } from 'mobx'
import { getUserInfo } from '../api/login'

class UserStore {
    userInfo = {}
    constructor() {
        makeAutoObservable(this)
    }

    getUserInfo = async ({ account }) => {
        const res = await getUserInfo({ account })
        if (res.code !== 'SUCCESS') return
        console.log('用户个人信息res', res);
        this.userInfo = res.data
        // console.log('用户信息', this.userInfo);

    }
}
export default UserStore

改进之后:

import { makeAutoObservable, runInAction } from 'mobx'
import { getUserInfo } from '../api/login'

class UserStore {
    userInfo = {}
    constructor() {
        makeAutoObservable(this)
    }

    getUserInfo = async ({ account }) => {
        const res = await getUserInfo({ account })
        if (res.code !== 'SUCCESS') return
        console.log('用户个人信息res', res);
        runInAction(() => {
            this.userInfo = res.data
        })
        // console.log('用户信息', this.userInfo);

    }
}
export default UserStore

控制台报警告的原因其实是mobx中只能在acrion中重新赋值,异步导致赋值操作被加载到队列中,在action外面了,
runInAction 函数将赋值操作包裹在action内部.

3.关闭scss文件自动生成的css文件和min.css文件

每次创建.scss文件后,添加我们自己的样式,总是会多出两个不必要的css文件,看着挺讨人厌的,现在我们将其关闭一下。

(1)找到设置打开它

(2)在搜索框里搜索easysass,并点击在setting.json中编辑

 (3)添加以下代码

"easysass.excludeRegex": "false",
"easysass.formats": [
    {
      "format": "expanded",
      "extension": ""
    },
    {
      "format": "compressed",
      "extension": ""
    }
  ],

这样就不会再生成css文件了。

4.执行完npm run eject项目报错

react报错jsx: Using `babel-preset-react-app` requires that you specify `NODE_ENV` or `BABEL_ENV` envi

 查了一下,报错的原因是:eslint插件启动没有注入开发环境ENV,导致babel-preset-react-app无法解析

删除package.json中的eslintConfig配置

但是其实这样不能完美解决问题,推荐的做法是执行 npm run eject命令之前需要先提交一次我们的代码,因为执行这个操作时不可逆的,因为这个吃了点亏。

5.项目中建立全局样式

assets/styles/global.scss

建好全局样式文件后,引入到index.js中:

import './assets/styles/global.scss'//全局样式

验证一下全局样式有没有生效:

  <label className='test'>label</label>

可以看到样式效果有了,也就是全局样式生效了,然后就可以自定义自己的全局样式文件了。 

6.配置别名路径(用@代替src)

安装修改CRA配置的包:yarn add -D @craco/craco;

项目根目录下创建文件 craco.config.js (一定记得要和src同级,不要建错地方了)

craco.config.js中代码如下

const path = require("path")
module.exports = {
  webpack:{
    alias:{
      "@":path.resolve(__dirname,"src")
    }
  }
}

package.json中修改部分:

//将 start/build/test 三个命令改为craco方式
 "scripts": {
    "start": "craco start",
    "build": "craco build",
    "test": "craco test",
    "eject": "react-scripts eject"
  },

然后重启项目,发现@配置src是生效了,但是@后面没有任何提示,一点不好用,还得自己手写,这显然不是我们想要的效果,再来配置一下。

@别名路径提示

在根目录下创建jsconfig.json配置文件(一定记得和src处于同级位置)

 jsconfig.json添加如下代码:

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

再重启项目,发现@后有了智能提示,有了我们想要的效果。

7.封装react高阶组件(实现路由权鉴)

其实也就是要实现vue的路由前置守卫的功能,但是react并没有给提供像vue的beforeEach这样的方法,所以需要自己封装高阶组件,实现登陆有token,跳转主页,没有token(未登录),不能访问(拦截在登陆页面),再就是有token但是想回到登录页,也要实现拦截,核心就是这样的思路。

新建一个AuthComponent.js文件,建议放在公共组件里面

import { getToken } from '@/utils'
import { Navigate } from 'react-router-dom'

const AuthComponent = ({ children }) => {
    const isToken = getToken()
    if (isToken) {
            return <>{children}</>
    }
     else {
        return <Navigate to='/login' replace></Navigate>
    }

}

export {
    AuthComponent
}

然后引入到项目得根文件App.js中,哪个页面需要登陆才能访问,就包裹哪个组件,以主页home为例:

    <Route path='/' element={
              <AuthComponent>
                <Home />
              </AuthComponent>
            }>
            </Route>

这样就实现了路由鉴权,也就是登陆这一模块的控制。

8.vscode自动格式化插件配置说明(Prettier - Code formatter)

安装Prettier插件,会解决保存后代码自动对齐的问题,之前配置的有点问题,导致每次保存代码后,还得手动格式化代码,非常麻烦,这下一并解决一下。

安装完之后然后添加以下配置代码:

 // prettier相关设置
  // 使能每一种语言默认格式化规则
  "[html]": {
    "editor.defaultFormatter": "vscode.html-language-features",
  },
  "[javascript]": {
    "editor.defaultFormatter": "vscode.typescript-language-features",
  },
 
  "editor.formatOnSave": true, // 保存格式化
  // html不换行
  "js-beautify-html": {
    // 换行
    // "wrap_attributes": "force-aligned"
    // 不换行 
    "wrap_attributes": "auto",
    // "wrap_attributes": "aligned-multiple",
  },
  "prettier": {
    "printWidth": 300, // 代码宽度  js超过 300换行
    "bracketSameLine": true,
    "trailingComma": "none", //禁止随时添加逗号,这个很重要。找了好久
    "singleQuote": true, // 单引号不自动转换双引号
    "semi": false, // 不添加分号
    "proseWrap": "preserve", // 代码超出是否要换行 preserve保留
    "arrowParens": "avoid", // 箭头函数一个参数不加括号
  },
  "files.associations": {
    "*.html": "html"
  },
  "workbench.iconTheme": "vscode-icons",
  "backgroundCover.autoStatus": true,
 
  // 格式化vue文件
  "files.autoSave": "onFocusChange",
  "editor.fontSize": 14,  // 设置字体
  "editor.tabSize": 2,    // 设置tab位2个空格,设置后在页面可查看.
  "editor.tabCompletion": "on",  // 用来在出现推荐值时,按下Tab键是否自动填入最佳推荐值
  "editor.codeActionsOnSave": {
      "source.fixAll.eslint": true,
      "source.organizeImports": true    // 这个属性能够在保存时,自动调整 import 语句相关顺序,能够让你的 import 语句按照字母顺序进行排列
  },
  "editor.lineNumbers": "on",  // 设置代码行号
  "editor.formatOnSave": true,
  "terminal.integrated.shell.osx": "zsh",
  "workbench.iconTheme": "vscode-icons",
  "explorer.confirmDelete": false, 
  // #让vue中的js按"prettier"格式进行格式化
  "vetur.format.defaultFormatter.html": "js-beautify-html",
  "vetur.format.defaultFormatter.js":"prettier-eslint",
  "vetur.format.defaultFormatterOptions": {
      "js-beautify-html": {
          // #vue组件中html代码格式化样式
          "wrap_attributes": "force-aligned", //也可以设置为“auto”,效果会不一样
          "wrap_line_length": 200,
          "end_with_newline": false,
          "semi": false,            "singleQuote": true
        },
        "prettier": {
            "semi": false,
            "singleQuote": true,
            "editor.tabSize": 2
        },
        "prettyhtml": {
            "printWidth": 160,
            "singleQuote": false,
            "wrapAttributes": false,
            "sortAttributes": false
        }
    },
  // 设置编译器默认使用vetur方式格式化代码
  "[vue]": {
    "editor.defaultFormatter": "octref.vetur"
  },

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/471591.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python 中如何实现自动导入缺失的库?

在编写 Python 项目的时候&#xff0c;我们经常会遇到导入模块失败的错误&#xff1a; ImportError: No module named xxx或者ModuleNotFoundError: No module named xxx 导入失败&#xff0c;通常分为两种&#xff1a;一种是导入自己写的模块&#xff08;即以 .py 为后缀的文件…

你不想成长,生活总会逼着你成长,阿里P8架构师分享十年学习生涯

成为阿里P8&#xff0c;并不是一件容易的事情&#xff0c;我花了将近十年的时间&#xff0c;才达到了这样的目标。这十年间来&#xff0c;说辛苦也是真辛苦&#xff0c;但这些辛苦是让我感觉到满足的&#xff0c;毕竟这样的成功并不是人人都能够得来的。 为了成为阿里P8的这十…

Linux(ubuntu) 挂载磁盘

前言 很多博客写了一些格式化磁盘&#xff0c;分区等等&#xff0c;这和挂载磁盘的概念是混淆的。分区是为了安装系统&#xff0c;我们挂载磁盘肯定是已经安装好Ubuntu 系统了&#xff0c;分区干什么&#xff0c;误人子弟啊。 另外格式化磁盘并不是挂载磁盘必须的选项&#x…

55.网页设计规则#3_图片和插图

使用好的图片 图片类型 不同类型的图像&#xff1a;产品照片、故事性照片、插图、图案&#xff1b;使用图片来支持你网站的信息和故事。所以只使用相关的图片倾向于使用原始图片。如果不可能&#xff0c;请使用原始外观的图片&#xff08;而不是一般的图片&#xff01;&#…

Numpy方法总简单说明作用

NumPy的大部分代码都是用C语言写的&#xff0c;其底层算法在设计时就有着优异的性能&#xff0c;这使得NumPy比纯Python代码高效得多 NumPy&#xff08;Numerical Python&#xff09;是Python的一种开源的数值计算扩展。这种工具可用来存储和处理大型矩阵&#xff0c;比Python…

JAVAWeb10-Web 开发会话技术-Session-02

1. session 有什么用 ● 思考两个问题—抛砖引玉 不同的用户登录网站后&#xff0c;不管该用户浏览该网站的哪个页面&#xff0c;都可显示登录人的名字&#xff0c;还可以随时去查看自己的购物车中的商品, 是如何实现的?也就是说&#xff0c;一个用户在浏览网站不同页面时&a…

如何高效的学习接口自动化测试?从零开始学习接口自动化测试:选择合适的学习资源和编程语言

目录 引言&#xff1a; 一、学习前的准备 二、选择合适的学习资源 三、实践中学习 四、总结 引言&#xff1a; 在日常的软件开发过程中&#xff0c;接口自动化测试是一个非常重要的环节。接口自动化测试可以帮助我们快速准确地检测出软件中的缺陷&#xff0c;提高软件的质…

更简单的存取Bean方式-@Bean方法注解

1.Bean方法存储 类注解是添加在某个类上的,那么方法注解是添加在某个方法前的 public class UserBeans {Beanpublic User user1(){User user new User();user.setUid(001);user.setUname("zhangsan");user.setAge(19);user.setPassword("123123");retur…

Git/Github操作手册

Git 是目前最流行的版本管理工具&#xff0c;也是程序员的必备技能之一。 这里主要介绍一下git/github远程仓库的使用及相关配置&#xff1a; 一、SSH Keys SSH Keys是什么呢&#xff1f;简单来说相当于一把钥匙&#xff08;在机器中即电脑中进行配置&#xff09;&#xff0…

【Java数据结构】——第九节.向上建堆和向下建堆的区别

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;Java初阶数据结构 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01;&#xff01; 文章目…

算法训练 | Day41动态规划

343. 整数拆分 思路&#xff1a; 确定dp数组&#xff08;dp table&#xff09;以及下标的含义&#xff1a;dp[i]&#xff1a;分拆数字i&#xff0c;可以得到的最大乘积为dp[i]。 确定递推公式&#xff1a;dp[i] max(dp[i], max((i - j) * j, dp[i - j] * j)) 可以想 dp[i]最…

TimesNet

Key Points 1D变2D 这是本文的核心。大部分现有方法都是作用于时间序列的时间维度&#xff0c;捕获时序依赖性。实际上&#xff0c;现实时间序列一般都有多种模式&#xff0c;比如不同的周期&#xff0c;各种趋势&#xff0c;这些模式混杂在一起。如果直接对原始序列的时间维…

SpringTask任务调度工具的使用

1. Spring Task 1.1 介绍 Spring Task 是Spring框架提供的任务调度工具&#xff0c;可以按照约定的时间自动执行某个代码逻辑。 **定位&#xff1a;**定时任务框架 **作用&#xff1a;**定时自动执行某段Java代码 应用场景&#xff1a; 1). 信用卡每月还款提醒 **强调&…

网络机顶盒哪个好?发烧友实测2023网络机顶盒排名

不懂网络机顶盒哪个好的新手们在选购时大部分会参考排行榜&#xff0c;某知名权威数码网站公布了2023年最新网络机顶盒排名&#xff0c;结果是否公正呢&#xff1f;我自费购入了排名前五的网络机顶盒&#xff0c;进行了十多天的深入测评&#xff0c;今天就来详细聊聊我的真实体…

最近部门新的00后真是卷王,工作没1年,入职18K

都说00后躺平了&#xff0c;但是有一说一&#xff0c;该卷的还是卷。 这不&#xff0c;前段时间我们公司来了个00后&#xff0c;工作都没1年&#xff0c;到我们公司起薪18K&#xff0c;都快接近我了。后来才知道人家是个卷王&#xff0c;从早干到晚就差搬张床到工位睡觉了。 …

2.2 逻辑代数中的三种基本运算

学习建议&#xff1a; 理解运算符的含义&#xff1a;首先&#xff0c;我们需要理解每个逻辑运算符的含义。例如&#xff0c;“与”运算符表示两个输入信号同时为真时输出为真&#xff0c;而“或”运算符表示两个输入信号中至少一个为真时输出为真。 练习运算符的应用&#xff…

使用openssl生成https证书

首先去官网下载openssl工具&#xff1a;Win32/Win64 OpenSSL Installer for Windows - Shining Light Productions (slproweb.com) 然后安装完成需要执行&#xff08;1&#xff09;openssl genrsa -des3 -out root.key 1024 &#xff08;2&#xff09;openssl req -new -key ro…

Java面试题总结 | Java面试题总结7- 计算机网络模块(持续更新)

计算机网络 文章目录 计算机网络get和post的区别TCP和UDPTCP和UDP的应用层协议TCP是如何保证可靠传输的视频聊天用的是TCP还是UDP&#xff0c;为什么可靠的UDP协议UDT(UDP-based Data Transfer Protocol)KCPQUIC Cookie和Session的区别Cookie的优缺点cookie的优点&#xff1a;c…

连ChatGPT都不懂的五一调休,到底怎么来的?

今天是周几&#xff1f; 你上了几天班了&#xff1f; 还要上几天班放假&#xff1f; 五一啥安排&#xff1f; 出行的票抢到了吗&#xff1f; 调休到底是谁发明的&#xff1f;&#xff01; 五一劳动节是要劳动吗&#xff1f; 为什么昨天是周一&#xff0c;今天还是周一&a…

跨域融合风口下,又一外资巨头Tier 1+本土供应商“组团”来袭

头部企业正在加速“融合”。 汽车智能化升级对产品创新与多元化需求下&#xff0c;来自技术升级、降本、开发周期缩短等等一系列因素影响&#xff0c;中外供应商们都在积极思变和寻求破局。 随着全球智能汽车产业步入域集中和域融合的新阶段&#xff0c;过去的以硬件&#xf…