返回顶部
首页 > 资讯 > 前端开发 > JavaScript >React错误的习惯用法分析详解
  • 387
分享到

React错误的习惯用法分析详解

React错误用法习惯React错误用法 2023-01-09 09:01:24 387人浏览 安东尼
摘要

目录过多的声明state问题解决方法不必要的state问题解决方法过多的useEffect问题解决方法请求竞争问题问题解决方法使用三元表达式代替&&使用 &&

过多的声明state

在我们React的日常开发中一些常用的写法,看似运行的很好,实际可能并不优雅。学习React并不是如何如何使用它,而是如何写出优雅,干净的代码。下面举一些例子,总结了一些React开发中不好的写法及相应更好的写法。(仅代表个人观点)

问题

一个组件中声明了过多的state,过多的setState方法。例如下面的这样:

import { useState } from "react";
export default function MoreState() {
  const [username, setUsername] = useState("");
  const [age, setAge] = useState("");
  const [gender, setGender] = useState("");
  const [email, setEmail] = useState("");
  const [passWord, setPassword] = useState("");
  const [address, setAddress] = useState("");
  const [city, setCity] = useState("");
  const onSubmit = () => {
    // ...
  };
  return (
    <fORM onSubmit={onSubmit}>
      <input
        type="text"
        name="username"
        placeholder="username"
        value={username}
        onChange={(e) => setUsername(e.target.value)}
      />
      <br />
      <input
        type="text"
        name="age"
        placeholder="age"
        value={age}
        onChange={(e) => setAge(e.target.value)}
      />
      <br />
      <input
        type="text"
        name="gender"
        placeholder="gender"
        value={gender}
        onChange={(e) => setGender(e.target.value)}
      />
      <br />
      <input
        type="text"
        name="email"
        placeholder="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
      />
      <br />
      <input
        type="text"
        name="password"
        placeholder="password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
      />
      <br />
      <input
        type="text"
        name="address"
        placeholder="address"
        value={address}
        onChange={(e) => setAddress(e.target.value)}
      />
      <br />
      <input
        type="text"
        name="city"
        placeholder="city"
        value={city}
        onChange={(e) => setCity(e.target.value)}
      />
      <br />
      <button type="submit">提交</button>
    </form>
  );
}

实际上这样并不好维护,接手项目的人都疯了?。还有这样的:

解决方法

把能合并的state,合并成一个对象表示。当然也可以使用useReducer。当属性中出现嵌套结构时,例如属性中有对象和数组时,使用useReducer更好一些。

import { useState } from "react";
export default function MoreState() {
  const [userInfo, setUserInfo] = useState({
    username: "",
    age: "",
    gender: "",
    email: "",
    password: "",
    address: "",
    city: ""
  });
  const onChange = (e) => {
    setUserInfo((pre) => ({ ...pre, [e.target.name]: e.target.value }));
  };
  const onSubmit = (e) => {
    e.preventDefault();
    console.log(111, userInfo);
  };
  return (
    <form onSubmit={onSubmit}>
      <input
        type="text"
        name="username"
        placeholder="username"
        onChange={onChange}
      />
      <br />
      <input type="text" name="age" placeholder="age" onChange={onChange} />
      <br />
      <input
        type="text"
        name="gender"
        placeholder="gender"
        onChange={onChange}
      />
      <br />
      <input type="text" name="email" placeholder="email" onChange={onChange} />
      <br />
      <input
        type="text"
        name="password"
        placeholder="password"
        onChange={onChange}
      />
      <br />
      <input
        type="text"
        name="address"
        placeholder="address"
        onChange={onChange}
      />
      <br />
      <input type="text" name="city" placeholder="city" onChange={onChange} />
      <br />
      <button type="submit">提交</button>
    </form>
  );
}

不必要的state

问题

我们在开发React表单时,通常会使用state来记录表单的值,例如:

import { useState } from "react";
export default function NoState() {
  const [username, setUsername] = useState("");
  const [password, setPassword] = useState("");
  const onSubmit = (e) => {
    e.preventDefault();
    console.log("需要提交的数据", username, password);
  };
  console.log("组件重新渲染了");
  return (
    <form onSubmit={onSubmit}>
      <label htmlFor="name">名字</label>
      <input
        type="text"
        value={username}
        onChange={(e) => setUsername(e.target.value)}
      />
      <br />
      <label htmlFor="name">密码</label>
      <input
        type="text"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
      />
      <br />
      <button type="submit">提交</button>
    </form>
  );
}

上面的代码看似并没有什么问题,但是我们只是在提交的时候用到了state,并没有在其他地方使用过这些state。这个例子中我们并不关心这些state值的变化,我们只关心我们提交的数据是否正确。而且我们每次输入的时候组件都是重新渲染。这并不友好,这个时候我们需要非受控组件。

解决方法

当表单元素不多时,使用ref来处理,并且每次输入都不会引起组件的重新渲染,因为这个时候我们只关心提交的数据,没有在其他地方使用过这些state。

import { useRef } from "react";
export default function NoState() {
  const usernameRef = useRef();
  const posswordRef = useRef();
  const onSubmit = (e) => {
    e.preventDefault();
    console.log(
      "需要提交的数据",
      usernameRef.current.value,
      posswordRef.current.value
    );
  };
  console.log("组件重新渲染了");
  return (
    <form onSubmit={onSubmit}>
      <label htmlFor="name">名字</label>
      <input type="text" ref={usernameRef} />
      <br />
      <label htmlFor="name">密码</label>
      <input type="text" ref={posswordRef} />
      <br />
      <button type="submit">提交</button>
    </form>
  );
}

过多的useEffect

问题

有时当页面第一次挂载时,我们需要进行网络请求,我们经常会这样写:

import { useEffect, useState } from "react";
export default function MoreUseEffect() {
  const [data, setData] = useState();
  useEffect(() => {
    fetch("/ss/ss").then((res) => {
      setData(res.data);
    });
  }, []);
  useEffect(() => {
    // 进行其他逻辑处理...
    console.log(data);
  }, [data]);
  return <>页面第一次加载时请求</>;
}

引入了过多的useEfffect,实际上我们只是需要使用请求到的数据来进行其他逻辑的处理,并不需要数据变化时做一些事情。

解决方法

把数据的处理逻辑放入第一个useEffect中直接处理。

import { useEffect } from "react";
export default function MoreUseEffect() {
  useEffect(() => {
    fetch("/ss/ss").then((res) => {
    	// setData(res.data);
      // 在这里直接进行数据处理...
      console.log('')
    });
  }, []);
  return <>页面第一次加载时请求</>;
}

请求竞争问题

问题

下面是对fetch请求进行了封装,这种写法有一个问题:当同时有多个请求时,由于请求返回的时间不一样,会出现竞争关系,不会按照请求的顺序返回结果,这样就造成返回的结果不知道是哪次的。

import { useEffect, useState } from "react";
export default function useFetch(url) {
  const [loading, setLoading] = useState(true);
  const [data, setData] = useState();
  const [error, setError] = useState();
  useEffect(() => {
    setLoading(true);
    fetch(url)
      .then((res) => {
        setData(res.data);
      })
      .catch((e) => {
        setError(e);
      })
      .finally(() => setLoading(false));
  }, [url]);
  return {
    loading,
    data,
    error
  };
}

解决方法

需要在请求URL变化之后取消前一次的请求。

import { useEffect, useState } from "react";
export default function useFetch(url) {
  const [loading, setLoading] = useState(true);
  const [data, setData] = useState();
  const [error, setError] = useState();
  useEffect(() => {
    const controller = new AbortController();
    setLoading(true);
    fetch(url, { signal: controller.signal })
      .then((res) => {
        setData(res.data);
      })
      .catch((e) => {
        setError(e);
      })
      .finally(() => setLoading(false));
    return () => {
      controller.abort();
    };
  }, [url]);
  return {
    loading,
    data,
    error
  };
}

使用三元表达式代替&&

使用 && 常见的错误

1.当状态值不是Boolean,而是数字0时,数字0会在UI中显示。

import { useState } from "react";
export default function MoreUseEffect() {
	const [arr] = useState([])
  return <>
    {
      arr.length && <div>11111</div>
    }
    </>;
}

解决方法

  • 转成Boolean
  • 使用三元表达式代替 && (推荐)

传递特殊属性ref

问题

ref属性是React的特殊属性,不能直接传递使用。

import {useRef} from 'react'
function InputCom({ref}) {
  return (
    <input type='text' ref={ref} />
  )
}
function App() {
  const inpRef = useRef(null)
  const focus = () => {
    inpRef.current?.focus()
  }
  return (
    <>
      <InputCom ref={inpRef} />
    </>
  )
}

如果想传递ref需要借助forwardRef函数。

解决方法

借助forwardRef转发ref属性

import { forwardRef, useRef } from "react";
// function InputCom({ ref }) {
//   return <input type="text" ref={ref} />;
// }
const InputCom = forwardRef((props, ref) => {
  return <input type="text" ref={ref} />;
});
export default function ProRef() {
  const inpRef = useRef(null);
  const focus = () => {
    inpRef.current?.focus();
  };
  return (
    <>
      <InputCom ref={inpRef} />
      <br />
      <button onClick={focus}>focus</button>
    </>
  );
}

以上就是React错误用法习惯分析详解的详细内容,更多关于React错误用法习惯的资料请关注编程网其它相关文章!

--结束END--

本文标题: React错误的习惯用法分析详解

本文链接: https://lsjlt.com/news/177121.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • React错误的习惯用法分析详解
    目录过多的声明state问题解决方法不必要的state问题解决方法过多的useEffect问题解决方法请求竞争问题问题解决方法使用三元表达式代替&&使用 &&...
    99+
    2023-01-09
    React错误用法习惯 React错误用法
  • React Context的用法分析
    这篇文章将为大家详细讲解有关React Context的用法分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。前言Context被翻译为上下文,在编程领域,这是一个经常会接触到的概念,React中也有。在...
    99+
    2023-06-14
  • React 错误边界Error Boundary使用示例解析
    目录我们为什么需要错误边界如何使用错误边界组件使用错误边界需要注意什么我们为什么需要错误边界 在React组件中可能会由于某些JavaScript错误,导致一些无法追踪的错误,导致应...
    99+
    2024-04-02
  • ReactuseState的错误用法避坑详解
    目录引言冗余的 state简单示例问题分析解决方案重复的 state简单示例问题分析解决方案使用 useEffect 更新 state简单示例问题分析解决方案使用 useEffect...
    99+
    2023-01-12
    React useState错误避坑 React useState
  • Oracle nvarchar2错误的问题分析及解决方法
    本篇内容主要讲解“Oracle nvarchar2错误的问题分析及解决方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Oracle nvarchar2错误的问...
    99+
    2024-04-02
  • react-redux的connect用法详解
    目录一、UI组件和容器组件二、connect1、导入2、使用三、mapStateToProps四、mapDispatchToProps五、Provider一、UI组件和容器组件 Re...
    99+
    2023-01-31
    react-redux的connect用法 react-redux使用
  • 前后端项目分离解决cors错误的方法详解
    目录前言一、什么是跨域请求二、配置类重写addCorsMappings方法三、controller添加@CrossOrigin注解四、使用nginx解决跨域请求总结前言 前后端分离项...
    99+
    2023-02-15
    cors错误怎么解决 cors报错 cors错误xhr类型
  • PHP 函数常见错误的详细解析
    php 函数常见的错误有:函数不存在:调用未定义的函数,解决方法是确保函数已定义或已包含。参数类型不匹配:传递的参数类型与函数签名不匹配,解决方法是传递正确类型的数据。错误的参数数量:参...
    99+
    2024-04-11
    php 错误解析 作用域
  • android layout XML解析错误的解决方法
    提示: org.xmlpull.v1.XmlPullParserException: PI must not start with xml (position:unknown ...
    99+
    2022-06-06
    XML 方法 xml解析 Android
  • php中json解析错误的解决方法
    这篇文章将为大家详细讲解有关php中json解析错误的解决方法,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。php json解析错误的解决办法:首先创建一个PHP示例文件;然后手动通过“json_last...
    99+
    2023-06-06
  • MySQL学习之分组查询的用法详解
    目录为什么要分组逐级分组逐级分组对 SELECT 子句的要求对分组结果集再次做汇总计算GROUP_CONCAT 函数GROUP BY 子句的执行顺序该章节来开始学习分组查询,上一章节我们学习了聚合函数,默认统计的...
    99+
    2022-07-28
    MySQL分组查询 MySQL 查询
  • Oracle分析函数用法详解
    一、概述 OLAP的系统(即Online Aanalyse Process)一般用于系统决策使用。通常和数据仓库、数据分析、数据挖掘等概念联系在一起。这些系统的特点是数据量大,对实时...
    99+
    2024-04-02
  • 分析Python的错误,调试和测试方法
    本篇内容主要讲解“分析Python的错误,调试和测试方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“分析Python的错误,调试和测试方法”吧!  错误处理  在预防程序发生运行错误的时候,可...
    99+
    2023-06-02
  • 示例详解react中useState的用法
    useState useState 通过在函数组件里调用它来给组件添加一些内部 state。React 会在重复渲染时保留这个 state。useState 会返回一对值:当前状态...
    99+
    2024-04-02
  • 总结分析Git pull 常见的错误及其解决方法
    在使用 Git 进行项目协作时,我们经常会使用 git pull 命令来同步远程仓库中的代码到本地。尽管这个命令非常简单易用,但有时候可能会遇到各种各样的错误,甚至导致项目无法正常运行。本文将分析 Git pull 常见的错误及其解决方法。...
    99+
    2023-10-22
  • ORACLE常见错误代码的分析与解决
    (一)在使用ORACLE的过程过,我们会经常遇到一些ORACLE产生的错误,对于初学者而言,这些错误可能有点模糊,而且可能一时不知怎么去处理产生的这些错误,本人就使用中出现比较频繁的错误代码一一做出分析,希...
    99+
    2024-04-02
  • React用法之高阶组件的用法详解
    目录监介使用HOC的原因HOC的实现方式属性代理反向继承属性代理和反向继承对比监介 高阶组件也就是我们常说的HOC,是React中用于复用组件逻辑的一种高级技巧。HOC自身不是Rea...
    99+
    2023-05-16
    React高阶组件用法 React 高阶组件 React 组件
  • Python学习笔记之解析json的方法分析
    本文实例讲述了Python解析json的方法。分享给大家供大家参考,具体如下: 刚学习到Python中解析json的方法,觉得有必要在这里坐下笔记。 我是在python的内部环境中看的 Encoding b...
    99+
    2022-06-04
    学习笔记 方法 Python
  • go高并发时append方法偶现错误解决分析
    目录背景排查问题解决问题背景 在实现图片转码的需求时,需要支持最大 500 个图片下载后转换格式; 如果是一个一个下载后转码,耗时太长,需要使用 goroutine 实现 500 个...
    99+
    2024-04-02
  • python机器学习算法与数据降维分析详解
    目录一、数据降维1.特征选择2.主成分分析(PCA)3.降维方法使用流程二、机器学习开发流程1.机器学习算法分类2.机器学习开发流程三、转换器与估计器1.转换器2.估计器一、数据降维...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作