资讯专栏INFORMATION COLUMN

React.js 常见问题

KitorinZero / 2831人阅读

摘要:我们常常会收到一些有趣的问题,但大多数问题都是常见问题。我创建这个资源为了帮助学习者遇到这些常见的问题时提供一定帮助。这些是表示没有任何子节点的元素的标记。不绑定处理程序方法我把这个留到最后,因为这是一个大问题,一个很常见的问题。

在 jsComplete,我们管理一个专门用于帮助编程学习者 slack 帐户。我们常常会收到一些有趣的问题,但大多数问题都是常见问题。 我创建这个资源为了帮助 React.js学习者遇到这些常见的问题时提供一定帮助。在这里可以快速找到一些常见问题的解决方案,而不是一,遍又一遍去找解决方法,我会持续更新这些常见的问题。

想阅读更多优质文章请猛戳GitHub博客,一年百来篇优质文章等着你!

1. 组件的名称开头要大写

React 组件名称必须具有以大写字母开头。

如果组件名称不以大写字母开头,则组件使用将被视为内置元素,例如 divspan

例如:

class greeting extends React.Component { 
  // ...
}

如果尝试渲染 ,React 将忽略上述内容,会报以下警告:

Warning: The tag  is unrecognized in this browser. If you meant to render a React component, start its name with an uppercase letter.

这里更大的问题是把组件命名为 buttonimg。 React 会忽略你的组件,只是渲染一个普通 HTML buttonimg 标签。

注意上面没有渲染 “My Awesome Button” 和 React 刚刚呈现的空 HTML 按钮元素。 在这种情况下,React 不会警告你。

2.使用单引号而不是反引号

用反引号(`…`)创建的字符串与用单引号("…")创建的字符串不同。

在大多数键盘上,可以使用 tab 键上方的键来输入用反引号( ` )字符。

当需要在字符串中包含动态表达式时,使用反引号创建一个字符串(不需要使用字符串连接)。

`This is a string template literal that can include expressions`
"This is just a string, you cannot include expressions here"

假设你想要一个始终报告当前时间的字符串:

“Time is ...”

// Current time string
const time = new Date().toLocaleTimeString();
// 使用普通字符串(单引号或双引号)时,需要使用字符串连接:
"Time is " + time
// 在使用反引号时,可以使用 ${} 在字符串中注入时间
`Time is ${time}`

此外,反引号还声明一个字符串时,可以创建一个跨多行的字符串:

const template = `I
CAN
SPAN
Multiple Lines`;

常规字符串不能这样做。

3. 使用 React.PropTypes

PropTypes 对象已从 React 中删除。 其过去是以 React.PropTypes 的形式被使用,但不能再使用它了。

相应的,你需要:

npm install prop-types

import PropTypes from "prop-types"

然后就可以使用它啦,如: PropTypes.string

如果你错误地使用了 React.PropTypes,会得到这样的错误提示:

TypeError: Cannot read property "string" of undefined
4. 没有使用指南里指定的版本

在看或阅读有关代码的内容以及使用指南里的例子时,确保你使用的库版本与例子的里的版本是一致的。一般使用最新版本是没有问题,但是如果内容过时,你可能会遇到一些弃用问题。

为了安全起见,请使用主干版本。 例如,如果教程里使用的是 React 16,自己就不要使用 React 15 进行开发了。

这对 Node.js 也很重要。如果使用旧版本的 Node,会遇到一系列问题。 例如,如果你正在看一些教程,这些教程使用了 Object.values,而你现在用 Node 6.x,那个版本此方法是不存在的。 你需要 Node 7.x 或更高版本。

5. 令人困惑的函数与类

你能看出下面的代码有什么问题吗?

class Numbers extends React.Component {
  const arrayOfNumbers = _.range(1, 10);
  // ...
}

上面的代码是无效的,因为在 JavaScript 类的内部,不能随意定义变量,只能使用规定的语法定义方法和属性。

这有点令人困惑,因为类语法中使用的{}看起来像块级作用域,但它并不是。

在一个由函数构成的组件里,你就可以想怎么搞就怎么搞:

// Totally Okay:
const Number = (props) => {
  const arrayOfNumbers = _.range(1, 10);
  // ...
};
6. 将数字作为字符串传递

你可以通过 prop 属性传递一个字符串:


如果需要传递一个数值,不要使用字符串:

// 不要这样做

相反,使用花括号传递一个实际的数值:


在 Greeting 组件中使用 {7}this.props.counter 就被赋值为数字 7 ,并且可以对其进行数学运算。 如果将其作为“7”传递,然后将其视为数字,则可能会遇到意外结果。

7. 忘记了另外一个 app 在用同样的端口

要运行 web 服务器,需要使用主机(如 127.0.0.1 )和端口(如 8080)使服务器侦听有效 http 地址上的请求。

一旦成功运行,web 服务器就占据了那个端口,你就不能让这个端口它用,端口会被占用。

如果你尝试在另一个终端上运行相同的服务器,将会得到端口被占用的错误提示,如下:

Error: listen EADDRINUSE 127.0.0.1:8080

请注意,有时 Web 服务器可能在后台运行或在分离的屏幕/tmux 会话中运行。你看不到,但它仍然占据了端口。 要重新启动服务器,需要“杀死”仍在运行的服务器。

要识别使用某个端口的进程,可以使用 ps 之类的命令(以及关于应用程序的grep),或者如果你知道端口号,则可以使用 lsof 命令:

lsof -i :8080

8. 忘记创建环境变量

有些项目依赖于 shell 环境变量的存在才能启动。 如果在没有所需环境变量的情况下运行这些项目,它们将尝试为它们使用未定义的值,并可能会给你一些神秘的错误。

例如,如果项目连接到像 MongoDB 这样的数据库,则可能会使用像 process.env.MONGO_URI这样的环境变量来连接它。 这允许项目与不同环境中的不同MongoDB 实例一起使用。

要在本地运行连接到 MongoDB 的项目,首先必须导出 MONGO_URI 环境变量。 例如,如果你在端口 27017 上运行本地 MongoDB,则需要在运行项目之前执行此操作:

export MONGO_URI="mongodb://localhost:27017/mydb"

你可以 grep 项目源代码,找到 process.env 来查清楚其运行正常所需要的环境变量。

9. 把花括号{}和圆括号()搞混

不要用:

return {
  something();
};

这样用:

return (
  something();
);

第一个将尝试(并且会失败)返回一个对象,而第二个将正确调用 something() 函数并返回该函数返回的内容。

因为 JSX 中的任何 都将转换为函数调用,所以在返回任何 JSX 时都会出现这个问题。

这个问题在箭头函数的缩写语法中也很常见。

不要用:

const Greeting = () => {
  
Hello World
};

这样用:

const Greeting = () => (
  
Hello World
);

当你使用带有箭头函数的中括号时,你就新起了一个函数的作用域。箭头函数的缩写语法不用中括号。

10. 不使用圆括号包装对象

当你想要创建一个返回普通对象的箭头函数时,上面的花括号和圆括号问题也会让你感到困惑。

不要用:

const myAction = () => { type: "DO_THIS" };

这样用:

const myAction = () => ({ type: "DO_THIS"});

如果没有把对象包裹在圆括号里,你就不能使用缩写语法。实际上你会给字符串定义一个标签。

这在 setState 方法的 updater 函数中很常见,因为它需要返回一个对象。 如果要使用箭头函数语法,则需要用括号包装该对象。

不要用:

this.setState(prevState => { answer: 42 });

这样用:

this.setState(prevState => ({ answer: 42 }));

11. 没有正确使用API元素和属性的大小写

使用 React.Component,而不是 React.component。 使用 componentDidMount,而不是 ComponentDidMount。使用 ReactDOM,而不是ReactDom

请注意需要的 API 大小写。 如果使用不正确的大小写,得到的错误信息可能不会很明确。

reactreact-dom 导入时,确保引入正确的名称,并且使用的内容与引入完全相同,ESLint 可以帮助你指出未使用的内容。

在处理组件属性时也会遇到这种问题:


// 在组件内部,你需要使用 props.userName 来获取传入的值

如果你没有使用 props.userName,而是 props.usernameprops.UserName,你会相当于用了一个 undefined 的值。需要特别留意下这点,当然更好的是配置 ESLint,它也能指出这些问题。

12. 将 state 对象与实例属性搞混

在类组件中,可以定义本地 state 对象,然后使用 this 访问它:

class Greeting extends React.Component {
  state = {
    name: "World",
  };
  render() {
    return `Hello ${this.state.name}`;
  }
}

以上代码会输出 “Hello World”

state 之外,你还可以定义其它本地实例属性。

class Greeting extends React.Component {
  user = {
    name: "World",
  };
  render() {
    return `Hello ${this.user.name}`;
  }
}

以上代码也会输出 “Hello World”

state 实例属性是一个特殊属性,因为 React 会管理它。 你只能通过 setState 更改它,当你这样做时 React 会做出响应。

然而,定义的所有其他实例属性对渲染算法没有影响。 你可以根据需要在上面的示例中更改this.user,并且 React 不会在React中触发渲染机制。

13. 将 搞混

在闭合标签里放错 / 字符。不可否认,有时你可以使用 ,而其他时间你需要

在 HTML 中,有一种称为“自闭合标签”(AKA void tag)。这些是表示没有任何子节点的元素的标记。例如,img 标签是一个自闭合标签:

// 不必使用 

以下方式是非法的:

// 错误
  

如果放错放了 / 字符的位置,将收到如下错误:

Syntax error: Unterminated JSX contents
14. 假设 import/export 起作用

import/export 特性是 JavaScript 中的官方功能(自2015年起)。 其只是 ES2015 的特性,并且还没有在流行浏览器和最新版 Node 里面被完整支持。

React 项目的流行配置使用 Webpack 和 Babel。 两者都允许使用此特性并将其编译为所有浏览器都能理解的内容。 只有工作流中有 Webpack 或 Babel 之类的转译工具,才能使用 import/export

但是,在 React 打包应用程序中 import/export 不意味着可以随意使用它们! 例如,如果你还通过最新的 Node 进行服务器端渲染,会行不通,你很可能会收到“unexpected token” 错误。

要让 Node 理解 import/export(如果你在前端使用它们就是你需要了解它们,并且也想要做 SSR 渲染的话),你需要有可以编译其的 Babel preset(像是_env_ preset),才能在Node 端运行。 你可以在开发时使用像 pm2_、 _nodemon 和 _babel-watch_的工具做到这点,,并在每次更改内容时重新启动 Node。

15. 不绑定处理程序方法

我把这个留到最后,因为这是一个大问题,一个很常见的问题。

你可以在 React 组件中定义类方法,然后在组件的 render 方法中使用它们。 例如:

class Greeting extends React.Component {
  whoIsThis() {
    console.dir(this); // "this" is the caller of whoIsThis
    return "World";
  }
  render() {
    return `Hello ${this.whoIsThis()}`;
  }
}
ReactDOM.render(, mountNode);

我在 render 里以 this.whoIsThis 的方式调用 whoIsThis 方法,因为在 render中,this 关键字指的是与表示组件的 DOM 元素关联的组件实例。

内部 React 确保其类方法中的 “this” 指向实例。 但是,当你使用 whoIsThis 方法的引用时,JavaScript 不会自动绑定实例。

whoIsThis 方法中的 console.dir 可以正确告诉我们当前组件实例,因为该方法是使用显式调用方(this)直接从 render 方法调用的。 执行上面的代码时,在控制台中看到Greeting 对象:

然而,当在延迟执行通道,例如事件处理里执行同样方法时,调用对象将不再是显性的,console.dir 也不会打印当前组件实例。

在上面的代码中,当单击字符串时,React 会调用 whoIsThis 方法,但它不会让你访问组件实例。 这就是我们点击字符串时得到 undefined 的原因。 如果类方法需要访问像this.propsthis.state 这样的属性,这会是一个问题,因为它根本行不通。

对于这个问题有很多解决方案。可以将方法包装在内联函数中,或使用 .bind 来改变 this 指向。 对于不经常更新的组件,两者都可以。

还可以通过在类的构造函数中而不是在 render 方法中执行来优化 bind 方法。 但是,此方法的最佳解决方案是通过 Babel 来使用 ECMAScript 类字段我(目前还是stage-3),这样对于处理程序只需使用箭头函数就可以了:

class Greeting extends React.Component {
  whoIsThis = () => {
    console.dir(this);
  }
  render() {
    return (
     
Hello World
); } }

这样会和预期一样执行:

代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug。

原文:

https://edgecoders.com/react-...

你的点赞是我持续分享好东西的动力,欢迎点赞!

欢迎加入前端大家庭,里面会经常分享一些技术资源。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/101659.html

相关文章

  • 写一本关于 React.js 的小书

    摘要:因为工作中一直在使用,也一直以来想总结一下自己关于的一些知识经验。于是把一些想法慢慢整理书写下来,做成一本开源免费专业简单的入门级别的小书,提供给社区。本书的后续可能会做成视频版本,敬请期待。本作品采用署名禁止演绎国际许可协议进行许可 React.js 小书 本文作者:胡子大哈本文原文:React.js 小书 转载请注明出处,保留原文链接以及作者信息 在线阅读:http://huzi...

    Scorpion 评论0 收藏0
  • React.js服务器渲染实例(React server side rendering exampl

    摘要:零基础学了快两个月的了,所谓的基础是指完全不懂,,还有任何相关概念,等等。这里说服务器渲染,是误打误撞了,我刚只是想把换掉而已。由负责将翻译成对应的文件顺带解决了语法问题。 零基础学了快两个月的React了(React-native + React.js),所谓的000基础是指完全不懂JS,CSS,HTML5还有任何相关概念Dom,Server rendering等等。PS:这里说服务...

    qpwoeiru96 评论0 收藏0
  • React.js 小书 Lesson9 - 事件监听

    摘要:在不需要手动调用浏览器原生的进行事件监听。没有经过特殊处理的话,这些的事件监听只能用在普通的的标签上,而不能用在组件标签上。的事件监听方法需要手动到当前实例,这种模式在中非常常用。下一节中我们将介绍小书组件的和。 React.js 小书 Lesson9 - 事件监听 本文作者:胡子大哈本文原文:http://huziketang.com/books/react/lesson9 转载请...

    yanbingyun1990 评论0 收藏0
  • React.js 最佳实践(2016)_链接修正版

    摘要:译者按最近依旧如火如荼相信大家都跃跃欲试我们团队也开始在领域有所尝试年应该是逐渐走向成熟的一年让我们一起来看看国外的开发者们都总结了哪些最佳实践年在全世界都有很多关于新的更新和开发者大会的讨论关于去年的重要事件请参考那么年最有趣的问题来了我 译者按:最近React(web/native)依旧如火如荼,相信大家都跃跃欲试,我们团队也开始在React领域有所尝试. 2016年应该是Reac...

    syoya 评论0 收藏0
  • 程序员练级攻略(2018):前端性能优化和框架

    摘要:,谷歌给的一份性能指南和最佳实践。目前而言,前端社区有三大框架和。随后重点讲述了和两大前端框架,给出了大量的文章教程和相关资源列表。我认为,使用函数式编程方式,更加符合后端程序员的思路,而是更符合前端工程师习惯的框架。 showImg(https://segmentfault.com/img/bVbjQAM?w=1142&h=640); 这个是我订阅 陈皓老师在极客上的专栏《左耳听风》...

    VEIGHTZ 评论0 收藏0
  • 程序员练级攻略(2018):前端性能优化和框架

    摘要:,谷歌给的一份性能指南和最佳实践。目前而言,前端社区有三大框架和。随后重点讲述了和两大前端框架,给出了大量的文章教程和相关资源列表。我认为,使用函数式编程方式,更加符合后端程序员的思路,而是更符合前端工程师习惯的框架。 showImg(https://segmentfault.com/img/bVbjQAM?w=1142&h=640); 这个是我订阅 陈皓老师在极客上的专栏《左耳听风》...

    CoffeX 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<