你知道学习一种新语言或框架的感觉。有时有很棒的文档可以帮助你找到方法。但即使是最好的文档也不能涵盖所有内容。当你处理新事物时,你一定会发现一个没有书面解决方案的问题。
这就是我第一次创建React项目时的情况——React是一个有着出色文档的框架,尤其是现在有了测试版文档。但我还是挣扎着度过了难关。这个项目已经过去很长一段时间了,但我从中得到的教训仍然历历在目。尽管有很多React“如何操作”教程,但我想我会分享我第一次使用它时希望知道的内容。
所以,这就是本文的内容——列出了我早期犯的错误。我希望它们能帮助你更顺利地学习React。
使用create-react应用程序启动项目
Create React App(CRA)是一个帮助您建立新React项目的工具。它为大多数React项目创建了一个具有最佳配置选项的开发环境。这意味着您不必花费时间自己配置任何内容。
作为一个初学者,这似乎是开始我工作的好方法!没有配置!开始编码!
CRA使用两个流行的包来实现这一点,即webpack和Babel。webpack是一个web捆绑器,它可以优化项目中的所有资产,如JavaScript、CSS和图像。Babel是一个允许您使用较新JavaScript功能的工具,即使某些浏览器不支持这些功能。
两者都很好,但有一些更新的工具可以做得更好,特别是Vite和Speedy Web编译器(SWC)。
这些新的和改进的替代方案比webpack和Babel更快、更容易配置。这使得在不弹出的情况下更容易调整配置,而在创建react应用程序时很难做到这一点。
要在设置新的React项目时同时使用它们,您必须确保安装了Node版本12或更高版本,然后运行以下命令。
npm create vite
您将被要求为您的项目选择一个名称。完成后,从框架列表中选择React。之后,您可以选择Javascript+SWC或Typescript+SWC
然后,您必须将目录cd更改为您的项目,并运行以下命令;
npm i && npm run dev
这应该为您的网站运行一个URL为localhost:5173的开发服务器
就这么简单。
使用defaultProps
作为默认值
数据可以通过称为props的东西传递给React组件。它们就像HTML元素中的属性一样被添加到组件中,并且可以通过将传入的prop对象中的相关值作为参数来在组件的定义中使用。
// App.jsx
export default function App() {
return <Card title="Hello" description="world" />
}
// Card.jsx
function Card(props) {
return (
<div>
<h1>{props.title}</h1>
<p>{props.description}</p>
</div>
);
}
export default Card;
如果道具需要默认值,则可以使用defaultProp属性:
// Card.jsx
function Card(props) {
// ...
}
Card.defaultProps = {
title: 'Default title',
description: 'Desc',
};
export default Card;
使用现代JavaScript,可以破坏props对象,并在函数参数中为其分配一个默认值。
// Card.jsx
function Card({title = "Default title", description= "Desc"}) {
return (
<div>
<h1>{title}</h1>
<p>{description}</p>
</div>
)
}
export default Card;
这是更有利的,因为现代浏览器可以读取代码,而不需要额外的转换。
不幸的是,defaultProp确实需要一些转换才能被浏览器读取,因为不支持开箱即用的JSX(JavaScriptXML)。这可能会影响使用大量defaultProp的应用程序的性能。
不要使用propTypes
在React中,propTypes属性可用于检查组件是否被传递了其props的正确数据类型。它们允许您指定应用于每个道具的数据类型,如字符串、数字、对象等。它们还允许您指定是否需要道具。
这样,如果组件被传递了错误的数据类型,或者没有提供所需的道具,那么React将抛出一个错误。
// Card.jsx
import { PropTypes } from "prop-types";
function Card(props) {
// ...
}
Card.propTypes = {
title: PropTypes.string.isRequired,
description: PropTypes.string,
};
export default Card;
TypeScript在传递给组件的数据中提供了一个类型安全级别。所以,当然,当我刚开始的时候,propTypes是个好主意。然而,既然TypeScript已经成为类型安全的首选解决方案,我强烈建议使用它而不是其他任何东西。
// Card.tsx
interface CardProps {
title: string,
description?: string,
}
export default function Card(props: CardProps) {
// ...
}
TypeScript是一种通过添加静态类型检查在JavaScript之上构建的编程语言。TypeScript提供了一个更强大的类型系统,可以捕捉更多潜在的bug并改善开发体验。
使用Class组件
React中的类组件是使用JavaScript类创建的。它们有一个更面向对象的结构,还有一些额外的功能,比如使用this关键字和生命周期方法的能力。
// Card.jsx
class Card extends React.Component {
render() {
return (
<div>
<h1>{this.props.title}</h1>
<p>{this.props.description}</p>
</div>
)
}
}
export default Card;
比起函数,我更喜欢用类来编写组件,但JavaScript类对初学者来说更难理解,这可能会让人非常困惑。相反,我建议将组件编写为函数:
// Card.jsx
function Card(props) {
return (
<div>
<h1>{props.title}</h1>
<p>{props.description}</p>
</div>
)
}
export default Card;
函数组件只是返回JSX的JavaScript函数。它们更容易阅读,并且并没有像this关键字和生命周期方法这样的附加功能,这使它们比类组件更具性能。
功能组件还具有使用钩子的优点。React Hook允许您在不编写类组件的情况下使用状态和其他React特性,使您的代码更具可读性、可维护性和可重用性。
不必要地导入React
由于React 17于2020年发布,现在无论何时创建组件,都没有必要在文件顶部导入React。
import React from 'react'; // Not needed!
export default function Card() {}
但我们必须在React 17之前这样做,因为JSX转换器(将JSX转换为常规JavaScript的东西)使用了一个名为React.createElement的方法,该方法仅在导入React时有效。从那时起,一个新的转换器已经发布,它可以在不使用createElement方法的情况下转换JSX。
您仍然需要导入React以使用钩子、片段以及库中可能需要的任何其他函数或组件:
import { useState } from 'react';
export default function Card() {
const [count, setCount] = useState(0);
// ...
}
这些都是我早期的错误!
也许“错误”这个词太苛刻了,因为后来出现了一些更好的做法。尽管如此,我还是看到了很多“旧”做事方式仍在项目和其他教程中被积极使用的例子。
老实说,我刚开始的时候可能犯了五个以上的错误。任何时候你接触到一个新工具,都更像是一次有效使用它的学习之旅,而不是切换开关。但这些都是我多年后仍然随身携带的东西!
如果你已经使用React一段时间了,你希望在开始之前知道哪些事情?如果能推出一个系列来帮助其他人避免同样的困难,那就太好了。