专栏首页前端全栈开发者新手React开发人员做错的5件事

新手React开发人员做错的5件事

请勿执行的操作以及如何解决的方法,这部分内容是针对React的新手开发人员提供的。

1.忘记大写React组件

考虑一下这段代码,它创建一个简单的div,其中包含父组件的标题。里面有一个子组件,其中包含带有一些文本的div。

class childComponent extends React.Component {
  render() {
    return (
      <div className='childDiv'>
        <p>Child Component</p>
      </div>
    );
  }
}

class ParentComponent extends React.Component {
  render() {
    return (
      <div className='parentDiv'>
        <h1 className='parentHeader'>Parent Component</h1>
        <childComponent />
      </div>
    );
  }
}

export default ParentComponent;

您认为代码运行时会出现什么?

childComponent 未渲染。它去哪儿了?代码编译成功,终端也没有错误。

再次查看子组件的代码。注意组件的名称,你注意到什么不同了吗?

在浏览器中打开控制台,浏览器控制台警告的大小写不正确

事实证明,React将小写组件视为DOM标记。如果你是React的新手,你可能已经错过了React文档中的这个小细节。

如果不了解这一点,初学者常常会陷入这样的困惑:即他们的代码编译没有任何错误,到底哪里出了问题?

解决方法很简单,大写您的组件。

2.错误地调用收到的props

要访问由父组件传入的prop,子组件必须确保它们调用了正确的prop名称。

还可以使用另一个变量名将Props传递给子组件。考虑以下代码片段:

class ChildComponent extends React.Component {
  render() {
    const { randomString } = this.props;

    return (
      <div className='childDiv'>
        <p>{randomString}</p>
      </div>
    );
  }
}

class ParentComponent extends React.Component {
  render() {
    const randomString = 'lorem ipsum';
    
    return (
      <div className='parentDiv'>
        <h1 className='parentHeader'>Parent Component</h1>
        <ChildComponent mainText={randomString} />
      </div>
    );
  }
}

尽管此代码可以编译并运行无误,但 ChildComponent 内不会渲染任何文本。

<ChildComponent mainText={randomString} />

仔细看看这一行代码,在 ParentComponent 中声明的变量 randomString 作为名为 mainText 的prop传递给 ChildComponent

然而,ChildComponent 试图从它收到的prop中访问 randomString。由于它仅接收 mainText 作为prop,因此将导致未定义的值分配给在 ChildComponent 中声明的 randomString。结果,其 <p>标记内未呈现任何内容。

注意哪些prop被传递到您的组件中,并相应地访问它们。这将在调试期间为您节省一些不必要的麻烦。

3.传递不正确的Props类型

如果所接收的prop不是预期的类型,那么依赖于这些接收prop的组件可能会有不同的行为。

class ChildComponent extends React.Component {
  render() {
    const { showIntro, showBody } = this.props;

    return (
      <div className='childDiv'>
        {showIntro && <p>Hello!</p>}
        {showBody && <p>Spot the mistake!</p>}
      </div>
    );
  }
}

考虑这个有两个prop的 ChildComponentshowIntroshowBody。它显示“你好!和“发现错误!”只有当showIntroshowBody 分别设置为 true 时才会这样。

ChildComponent 希望将两个布尔值作为prop传递。如果在父组件中执行类似的操作,会发生什么情况?

<ChildComponent showIntro='false' showBody='false' />
<ChildComponent showIntro={'false'} showBody={'false'} />
<ChildComponent showIntro={false} showBody={false} />

在prop中使用了不同的引号和大括号。但是,它们的行为将不同。看看这个:

前两个 ChildComponent 都渲染了两个 <p> 标记,而最后一个 ChildComponent 没有渲染。

作为prop传递的 'false'{'false'} 会导致无意中为 showIntroshowBody 分配了一个值为 false 的字符串,而不是布尔值 false

对于前两个 ChildComponent,将 showIntroshowBody 都计算为 true

这是由于 && 运算符的隐式强制类型转换。当 && 运算符检查 showIntroshowBody(均为字符串)时,两个字符串都将强制为 true

最后一个 ChildComponent 接收到布尔值 false,因此它没有正确渲染任何内容。

console.log(`showIntro type: ${typeof showIntro}`);
console.log(`showIntro evaluated to: ${showIntro && true}`);
console.log(`showBody type: ${typeof showBody}`);
console.log(`showBody evaluated to: ${showBody && true}`);

为了确认这一点,我们运行 console.log() 来检查每个 ChildComponent 中prop的运行结果。

正如这里所演示的,初学者在将prop传递给其他组件时能够区分使用引号和花括号之间的区别是非常重要的。

您可以使用引号来传递字符串文字。

<MyComponent data='Hello World!'/> // passing in a String

花括号用于传递JavaScript表达式。

<MyComponent data={2468} /> // passing in a Number
<MyComponent data={true} /> // passing in a Boolean

以下是Reac文档中的一些注意事项:

将JavaScript表达式嵌入属性中时,请勿在大括号周围加上引号。您应该使用引号(用于字符串值)或大括号(用于表达式),但不要在同一属性中都使用引号。

4.在render()内部调用setState()

下图无限循环错误消息

尽管您的组件中没有 componentWillUpdate()componentWillUpdate(),您仍可能遇到此错误。当您在 render() 函数中调用 setState() 时也会发生此错误。

为什么会这样?每次调用 setState() 时,React将通过调用 render() 重新渲染。您的 render() 函数内部是什么? setState()。你看到结果了吗?一个无限循环。

只需将 setState() 调用移到 render() 函数之外即可。

如果在组件挂载后必须初始化状态(也许是从API端点提取数据),请在 componentDidMoun() 中进行。

如果可以在组件挂载之前初始化状态,也可以使用构造函数来完成。

5.setState()的异步性

在调试时,通常使用 console.log() 打印值。但是,当代码异步运行时,这不能很好地工作。

handleCounterIncrement = () => {
  const { counter } = this.state;
  console.log(`Before update: ${counter}`);
  this.setState({ counter: counter + 1 });
  console.log(`After update: ${counter}`);
};

你以前试过这样做吗?坏消息——setState() 调用是异步的。不能保证给定的代码将按顺序执行。它可能导致如下输出:

在执行 setState() 之前执行了两个 console.log() 调用。因此,它两次打印前一个状态的值。

如果希望在调用 setState() 之前和之后检查状态的值,请在 setState() 中将回调作为第二个参数传递。

handleCounterIncrement = () => {
  const { counter } = this.state;
  console.log(`before update: ${counter}`);
  this.setState({ counter: counter + 1 }, () => {
  	console.log(`after update: ${this.state.counter}`);
  });
};

回调将在 setState() 完成后执行,从而为 console.log() 提供同步行为。


原文:https://medium.com/better-programming/5-things-novice-react-developers-do-wrong-9d97bd6dae95

作者:Jeremy Aw


本文首发于微信公众号《前端外文精选》,关注即送大礼包,准能为你节省不少钱!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 小程序组件开发之时间轴组件及组件关系

    先简单介绍一下公司业务和前端项目情况吧。公司是做金融行业财富管理的业务,涉及主要是做基金、保险这一块。前端项目目前涉及B端后台管理系统、C端小程序、Node服务...

    张张
  • 漫谈AOP开发之开发Spring AOP程序

    我们在Eclipse中创建一个新的工程,导入UserService、BookService两个类,并配置Spring的Bean:

    张张
  • 2020年的12个Vue.js开发技巧和窍门

    随着Vue 2.6的推出,已经引入了插槽的简写方式,可用于事件(例如,@click 表示 v-on:click 事件)或冒号表示方式用于绑定(:src)。例如,...

    张张
  • 如何管理好10万行代码的前端单页面应用

    蚂蚁金服数据平台前端团队主要负责多个数据相关的PC Web单页面应用程序,业务复杂度类比Excel等桌面应用,业务前端代码量在几万行~几十万行,随着产品不断完善...

    疯狂的技术宅
  • Spring注解之@Lazy注解,源码分析和总结

    关于延迟加载的问题,有次和大神讨论他会不会直接或间接影响其他类。spring的好处就是文档都在代码里,网上百度大多是无用功。

    ydymz
  • Day15:反转链表

    背景知识介绍   在做本题之前首先介绍一下链表的基本知识。在维基百科中,链表 是这样定义的:链表(Linked list)是一种常见的基础数据结构,是一种线...

    stefan666
  • iOS漫谈——对于项目架构的思考

    又一次的版本更新上架,心情容不得片刻舒缓,新的迭代任务又明白的摆在桌面上。今年上半年自己琢磨完ReactiveCocoa之后,对手上了项目做了MVVM架构的尝试...

    Originalee
  • 微信思维——不做骑马的步兵

    2013年10月,唯品会的一年一度的战略会议上唯品会董事长沈亚当场“发难”,2014年唯品会来自移动端销售占比要超过28%。

    腾讯大讲堂
  • Redis 模块机制 - 模块编写篇

    在 Redis 应用中,模块机制是提及得比较少的一个功能,主要是 Redis 的功能基本上能应付各种需求,很少需要自己编写模块来扩展功能的。但有时候我们希望为 ...

    用户7686797
  • 学界 | MIT周博磊团队:时序关系网络帮助计算机填补视频帧之间的空白

    AI 科技评论按:如果你向一个人仅仅展示一段视频中的几帧,他通常可以推测出视频里发生的是什么事件以及屏幕上会显示出什么。例如,如果我们在视频开始时的帧中看到了一...

    AI科技评论

扫码关注云+社区

领取腾讯云代金券