添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
苦恼的馒头  ·  React TreeSelect ...·  1 周前    · 
失落的勺子  ·  React那些事儿 · Issue ...·  1 周前    · 
忐忑的登山鞋  ·  @wellbees/color-picker ...·  1 周前    · 
苦恼的椰子  ·  next/link | Next.js | ...·  5 天前    · 
没有腹肌的胡萝卜  ·  STARTUP JS ERROR in ...·  23 小时前    · 
酒量小的人字拖  ·  GitHub - ...·  9 月前    · 

1、react 中 a 标签链接报错:Warning: A future version of React will block javascript: URLs as a security precaution.

当项目中 a 标签的 href 值为 javascript:; 或者 javascript:void() 时,在编译中会报错,具体报错信息如下:
Warning: A future version of React will block javascript: URLs as a security precaution.
Use event handlers instead if you can. If you need to generate unsafe HTML try using dangerouslySetInnerHTML instead. React was passed “javascript:;”.

解决方案 href 后面不用赋值,但要给点击事件加上 preventDefault ,即:

<a onClick={(e) => e.preventDefault()}>点我</a>
<!-- 如果需要判断href,像下面这样写可以 -->
<a href="link ? link : '#'" onClick={(e) => !link && e.preventDefault()}>点我</a>

2、‘XXX’ implicitly has an ‘any’ type

TS 项目在接收参数时使用了参数解构,遇到了如下警告提示: Binding element ‘XXX’ implicitly has an ‘any’ type

遇到这种解构参数识别不到类型的,只需要给该参数补上类型声明即可。
rowTyperow 对象的类型声明,当然也可以直接声明为 any

const text= ({ row }: { row: rowType })=>{
	// ...

3、typescript 报错 Cannot find name “__dirname”

这通常是由于 tsconfig.js 配置的问题

1). 将 node 添加到 tsconfig.json 文件中的 compilerOptions.types

"compilerOptions": { "types": [ "node"

2). 安装@types/node

yarn add @types/node --save-dev

4、动态加载/切换组件

使用 React.lazyReact.Suspense 来加载即可,这样也方便后面配合 webpacksplitchunks 做代码拆分。

import React, { Suspense, lazy, useState, useCallback } from "react";
import "./styles.css";
export default function App() {
  const [DynamicModule, setDynamicModule] = useState("div");
  const onClick = useCallback((e) => {
    let newName = e.target.dataset.name;
    setDynamicModule(
      lazy(() => import(/* webpackMode: "eager" */ `../modules/${newName}`))
  }, []);
  return (
    <div className="App">
      <button data-name="moduleA" onClick={onClick}>
      </button>
      <button data-name="moduleB" onClick={onClick}>
      </button>
          <Suspense fallback={<div>"loading"</div>}>
            <DynamicModule />
          </Suspense>

5、hooks 中使用 await

useEffect 的回调参数返回的是一个清除副作用的函数。因此无法返回 Promise,更无法使用 async/await,那我们有什么办法来让它支持 async/await 呢?

1). 方法一(推荐):useEffect 中异步函数采用 IIFE 写法( Immediately Invoked Function Expression 即立即调用的函数式表达式)

const MyFunctionnalComponent: React.FC = props => {
  useEffect(() => {
    // Using an IIFE
    (async function anyNameFunction() {
      await loadContent();
    })();
  }, []);
  return <div></div>;

2). 方法二:此时可以选择再包装一层 async 函数,置于 useEffect 的回调函数中,变相使用 async/await

const fetchMyAPI =async()=> {
  let response = await fetch('api/data')
  response = await res.json()
  dataSet(response)
useEffect(() => {
  fetchMyAPI();
}, []);

3). 方法三:在内部创建一个异步函数,等待 getData(1) 结果,然后调用 setData():

useEffect(() => {
  const fetchMyAPI = async () =>{
    const data = await getData(1);
    setData(data)
  fetchMyAPI();
}, []);

6、TypeScript 项目报错 Cannot use import statement outside a module, Unknown file extension “.ts“

解决方法:只需要在 tsconfig.js 里添加 "module": "commonjs" 即可。

7、useEffect 中清除 setTimeout 等副作用

useEffect 函数体中是当前的副作用,它也可以返回一个函数用来清除当前的副作用。

useEffect(() => {
  let timer = setTimeout(() => {}, 1000)
  return ()=> clearTimeout(timer)
}, [])

8、从枚举类型中提取 key 或 value 组成的联合类型(枚举类型转联合类型)

有时候,我们想通过之前定义的枚举类型中提取出可用的联合类型,比如提取其中的 key 或者 value 组成的联合类型,以下是相关用法示例:

enum EnumFruit = {
	orange:  'Orange',
  apple:  'Apple' ,
  banana: 'Banana'
// 获取枚举类型的 key 组成的联合类型
type KeyUnion = typeof EnumFruit // 'orange' | 'apple' | 'banana'
// 获取枚举类型的 value 组成的联合类型
type ValueUnion = `${EnumFruit}` // 'Orange' | 'Apple' | 'Banana'

9、interface 中的联合类型验证不通过

当我们在 interface 中定义了一个类型为联合类型的属性,在赋值的时候就会出现这类错误,如下示例:

interface Fruit {
	fruit: 'Orange' | 'Apple' | 'Banana',
    count: number
const fruitList:Fruit[] = [{fruit: 'Apple', count: 6 }]
// Type 'string' is not assignable to type '"Orange" | "Apple" | "Banana"'

到这种情况可以考虑使用 对象字面量 以及 typeofkeyof 推断相关类型:

const FruitObj = {
  orange:  'Orange',
  apple:  'Apple' ,
  banana: 'Banana'
} as const  // 一定要加 as const,不然没用
interface Fruit {
  fruit: typeof FruitObj[keyof typeof FruitObj]
  count: number
const fruitList:Fruit[] = [{fruit: 'Apple', count: 6 }]

参考文章:

  • literal-union-type-vs-string-enums
  • How do I a union type of string values from an enum?
  • 10、Type ‘undefined’ cannot be used as an index type

    当我们在 TS 中使用中括号动态访问对象中的某个属性或者数组中的某个值时,可能会提示这个错误。主要是由于 TS 无法确定这个动态属性的值导致的。如下例子所示:

    // 👇️ key is optional (could be undefined)
    const obj1: { key?: string } = {
      key: 'name',
    const obj2 = {
      name: 'James Doe',
    // ⛔️ Error: Type 'undefined' cannot be
    // used as an index type.ts(2538)
    const result = obj2[obj1.key];
    

    因此,我们需要对这个动态属性添加类型守卫(type guard),在使用前判断一下,如果不为 undefined 才使用,并且使用 as 把它断言为对象的 key,代码如下:

    if (obj1.key != undefined) {
      result = obj2[obj1.key as keyof typeof obj2];
    console.log(result); // 👉️ "James Doe"
    

    参考:Type ‘undefined’ cannot be used as an index type in TS

    11、‘React’ refers to a UMD global, but the current file is a module. Consider adding an import instead

    出现这个错误应该是 ts 的版本和 React 有冲突,可以通过配置 tsconfig.json 文件中的 jsx 属性解决。相关 issue

    "jsx": "preserve",
    

    12、路由懒加载的场景下,项目发版后导致没有刷新的用户出现js文件加载失败: ChunkLoadError: Loading chunk 42 failed.

    这种情况主要是由于浏览器缓存导致的,一般为了避开缓存的影响,我们打包出来的文件名都会带上唯一的 hash 值,但是当我们发版本后,那些没有刷新页面的用户在切换页面的时候,就会出现加载 js 出错的问题,而且一般发生在单页面的场景下。

    解决方法:

  • 去除 index.html 文件的缓存(Nginx 中的缓存设置排除一下 html 文件)
  • 为路由文件配置 ErrorBoundary,提示用户刷新,本质是利用 componentDidCatch 生命周期
  • 项目经常上线导致没有刷新的用户出现 js 文件加载失败: ChunkLoadError: Loading chunk 42 failed
  • ErrorBoundary 示例
  • class ErrorBoundary extends React.Component {
      constructor(props) {
        super(props);
        this.state = { error: null, errorInfo: null };
      componentDidCatch(error, errorInfo) {
        // Catch errors in any components below and re-render with error message
        this.setState({
          error: error,
          errorInfo: errorInfo
        // You can also log error messages to an error reporting service here
      render() {
        if (this.state.errorInfo) {
          // Error path
          return (
              <h2>Something went wrong.</h2>
              <details style={{ whiteSpace: 'pre-wrap' }}>
                {this.state.error && this.state.error.toString()}
                {this.state.errorInfo.componentStack}
              </details>
        // Normally, just render children
        return this.props.children;
    class BuggyCounter extends React.Component {
      constructor(props) {
        super(props);
        this.state = { counter: 0 };
        this.handleClick = this.handleClick.bind(this);
      handleClick() {
        this.setState(({counter}) => ({
          counter: counter + 1
      render() {
        if (this.state.counter === 5) {
          // Simulate a JS error
          throw new Error('I crashed!');
        return <h1 onClick={this.handleClick}>{this.state.counter}</h1>;
    function App() {
      return (
              This is an example of error boundaries in React 16.
              <br /><br />
              Click on the numbers to increase the counters.
              The counter is programmed to throw when it reaches 5. This simulates a JavaScript error in a component.
          <ErrorBoundary>
            <p>These two counters are inside the same error boundary. If one crashes, the error boundary will replace both of them.</p>
            <BuggyCounter />
            <BuggyCounter />
          </ErrorBoundary>
          <p>These two counters are each inside of their own error boundary. So if one crashes, the other is not affected.</p>
          <ErrorBoundary><BuggyCounter /></ErrorBoundary>
          <ErrorBoundary><BuggyCounter /></ErrorBoundary>
    const root = ReactDOM.createRoot(document.getElementById('root'));
    root.render(<App />);
    

    13、The operand of a ‘delete’ operator must be optional

    当我们在 TS 中使用 delete 删除对象的属性时,可能会遇到这个错误。

    interface Person {
      name: string
      age: number
    const person:Person = { name:'Jack', age: 20 }
    delete.name // The operand of a 'delete' operator must be optional
    

    strictNullChecks 中使用 delete 运算符时,操作数现在必须为 anyunknownnever 或为可选(因为它在类型中包含 undefined)。我们只需要确保要删除的那个属性为可选类型即可,如下:

    interface Person {
      name?: string
      age: number
    const person:Person = { name:'Jack', age: 20 }
    delete.name
    

    14、svg 压缩后,viewbox 属性丢失,导致图标展示异常

    在使用 @svgr/webpack 插件压缩 svg 之后,发现线上出现图标尺寸展示异常,经过检查,发现是 svg 的 viewbox 属性被移除导致的,此时只需要修改插件的配置即可。相关 issue

    test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, exclude: /node_modules/, use: [ loader: '@svgr/webpack', options: { svgoConfig: { plugins: [ { name: 'removeViewBox', active: false } // 保留 viewbox 属性,避免图标展示异常

    15、react 中渲染 html

    react 中需要通过 dangerouslySetInnerHTML 这个属性来渲染 html 内容

  • dangerouslySetInnerHTMLReact 标签的一个属性,类似于 angularng-bind
  • 有 2 个 {{}},第一个 {} 代表 jsx 语法开始,第二个是代表 dangerouslySetInnerHTML 接收的是一个对象键值对。
  • 既可以插入 DOM ,又可以插入字符串。
  • <div dangerouslySetInnerHTML={{__html: processResponsiveText(content)}}></div>
    

    16、The expected type comes from property ‘onClick’ which is declared here on type xxx

    出现这个错误主要是由于 TS 无法推断出当前 event 的类型导致的,我们只需要为 event 对象指定相应的类型即可,常用的可能会有 React.MouseEvent<HTMLDivElement>React.MouseEvent<HTMLButtonElement> ,如下例子使用到了 React.MouseEvent<HTMLDivElement> 这个类型:

    参考:Typescript and React: What is the proper type for an event handler that uses destructuring?

      const handleClick = ({
        currentTarget
      }: React.MouseEvent<HTMLDivElement>) => {
        setAnchorEl(currentTarget)
    <div onClick={handleClick}>点击我</div>
    

    17、Warning: validateDOMNesting(…): ‘td’ cannot appear as a child of ‘div’

    在使用 MUI 的 TablePagination 组件的时候,我遇到了这个问题,提示说的是 td 不应该作为 div 的子元素,这个组件内部使用了 datagrid 这个插件,他默认以 div 渲染,但是这个插件默认以 table 来渲染,最终 TS 会提示这个错误。

    经过查阅文档,发现该组件提供了一个 component 属性,可以指定它以何种元素来渲染。如下代码:

    <div className="w-full flex justify-end">
      <TablePagination
        sx={{ border: 'none' }}
        rowsPerPageOptions={[]}
        component="div"
        colSpan={3}
        count={total}
        labelDisplayedRows={() => null}
        rowsPerPage={rowsPerPage}
        page={page}
        onPageChange={handleChangePage}
        ActionsComponent={TablePaginationActions}
    

    18、React version not specified in eslint-plugin-react settings

    eslintrc.js 或者 .eslintrc 文件中添加如下配置项,让它自行检查版本信息即可:

    "settings": { "react": { "version": "detect"

    19、Received true for a non-boolean attribute xxx

    当我们在 React 中开发自定义组件的时候,如果定义了一个布尔类型的 prop,在使用这个组件的时候,如果我们直接传递布尔值或者只传递单个属性,React 都会抛出这个异常。

    // 定义一个Child组件
    const Child = ({visible}:{visible:boolean}) => {
    	return <div>{visible && <span>666</span>}</div>
    export default Child
    // 使用Child组件
    <Child visible/> // Received `true` for a non-boolean attribute
    <Child visible={true}/> // Received `true` for a non-boolean attribute
    

    这是 React 本身的限制(因为不带引号的 HTML 属性可能会导致许多问题),你需要改变一下写法:

    <Child visible={1}/>   // 用 0 和 1 代替布尔值
    <Child visible="true"/>  // 直接传递字符串形式(注意组件内部判断)
    // 还有如下写法也会抛出同样的异常
    // ❌ This will throw the above error
    <Component className={hidden && 'hidden'} />
    // ✔️ Use a ternary instead
    <Component className={hidden ? 'hidden' : undefined}  />
    

    参考How to fix the ‘Received “true” for a non-boolean attribute’ error

    🤠 希望能给遇到同样相关问题的你一点帮助,也为了记录。