npm创建react项目
Hooks are a handy addition to the React API that allow us to organize some of our logic and state in function components. How can we build a custom hook and share it with the rest of the world?
钩子是React API的便捷补充,它使我们能够在函数组件中组织一些逻辑和状态。 我们如何建立自定义钩子并与世界其他地方共享?
什么是钩子? (What are hooks?)
React hooks in simple terms are functions. When you include them in your component or within another hook, they allow you to make use of React internals and parts of the React lifecycle with native hooks like useState
and useEffect
.
简单来说,React 钩子就是函数。 当您将它们包含在组件中或另一个挂钩中时,它们使您可以通过本机挂钩(如useState
和useEffect
使用React内部和React生命周期的useState
useEffect
。
I don’t plan on doing a deep dive about hooks, but you can check out a quick introduction with an example of useState
as well as the intro from the React team.
我不打算对钩子进行深入研究,但是您可以通过useState
的示例以及React团队的介绍来 快速入门 。
为什么自定义挂钩很酷? (Why are custom hooks cool?)
The great thing about creating custom hooks is they allow you to abstract logic for your components making it easier to reuse across multiple components in your app.
创建自定义挂钩的好处在于,它们使您可以为组件抽象逻辑,从而可以更轻松地在应用程序中的多个组件之间重用。
For instance, if you wanted to create a simple counter where you use React’s state to manage the current count. Instead of having the same useState
hook in each component file, you can create that logic once in a useCounter
hook, making it easier to maintain, extend, and squash bugs if they come up.
例如,如果您想创建一个简单的计数器,您可以在其中使用React的状态来管理当前计数。 相反,具有相同的useState
每个组件文件挂钩,您可以创建一个逻辑曾经在useCounter
挂钩,使其更易于维护,扩展和壁球的bug,如果他们来了。
我们要做什么? (What are we going to make?)
For the purposes of this article, we’re going to keep it simple with a basic hook. Typically, you might use a hook because rather than a typical function, you use other native hooks that are required to be used within React function components. We’re going to stick with some basic input and output to keep things simple.
出于本文的目的,我们将使用基本的钩子使其保持简单。 通常,您可能会使用一个钩子,因为您使用了React函数组件中需要使用的其他本机钩子,而不是典型的函数。 我们将坚持一些基本的输入和输出,以使事情变得简单。
We’re going to recreate this custom Placecage hook I made, that allows you to easily generate image URLs that you can use as placeholder images.
我们将重新创建我制作的此自定义Placecage挂钩 ,该挂钩可让您轻松生成可用作占位符图像的图像URL。
If you’re not familiar, Placecage is an API that allows you to generate pictures of Nic Cage as placeholder images for your website. Silly? Yes. Fun? Absolutely!
如果您不熟悉, Placecage是一种API,可让您生成Nic Cage图片作为网站的占位符图像。 愚蠢? 是。 好玩吗 绝对!
But if you’re not a fan of Nic's work, you can just as easily swap in the URL for Fill Murray which uses pictures of Bill Murray or placeholder.com which generates simple solid color background with text that shows the size of the image.
但是,如果您不喜欢Nic的作品,则可以轻松地在Fill Murray的URL中交换,该URL使用Bill Murray的图片或placeholder.com来生成简单的纯色背景,并带有显示图像尺寸的文本。
步骤0:命名钩子 (Step 0: Naming your hook)
Before we jump in to our actual code, our ultimate goal is to publish this hook. If that’s not your goal, you can skip this step, but for publishing, we’ll want to create a name for our hook.
在跳到实际代码之前,我们的最终目标是发布该钩子。 如果这不是您的目标,则可以跳过此步骤,但是对于发布,我们将要为钩子创建一个名称。
In our case, our hook name will be usePlaceCage
. Now with that in mind, we have 2 formats of our name — one in camelCase format and one in snake-case format.
在我们的例子中,我们的钩子名称将为usePlaceCage
。 现在考虑到这一点,我们有两种名称格式-一种为camelCase格式,另一种为蛇形格式。
camelCase: usePlaceCage
camelCase: usePlaceCage
snake-case: use-placecage
蛇皮箱:使用笼子
The camelCase format will be used for the actual hook function, where the snake-case name will be used for the package name and some of the folders. When creating the name, keep in mind that the package name must be unique. If a package with the same name exists on npmjs.com already, you won't be able to use it.
camelCase格式将用于实际的挂钩函数,其中,蛇形名称将用于程序包名称和某些文件夹。 创建名称时,请记住包名称必须唯一。 如果npmjs.com上已经存在具有相同名称的软件包,则将无法使用它。
If you don’t already have a name, it's okay! You can just use your own name or something you can think of, it doesn’t really matter too much as really we're just trying to learn how to do this. If it were me for instance, I would use:
如果您还没有名字,没关系! 您可以使用自己的名称或可以想到的名称,这并不重要,因为实际上我们只是在尝试学习如何做。 例如,如果是我,我将使用:
camelCase: useColbysCoolHook
camelCase: useColbysCoolHook
snake-case: use-colbyscoolhook
蛇皮套: use-colbyscoolhook
But just to clarify, for the rest of our example, we’re going to stick with usePlaceCage
and use-placecage
.
但是为了澄清,在本示例的其余部分中,我们将继续使用usePlaceCage
和use-placecage
。
步骤1:建立专案 (Step 1: Setting up your project)
Though you can set up your project however you’d like, we’re going to walk through building a new hook from this template I created.
尽管您可以根据需要设置项目,但是我们将逐步从我创建的模板中构建一个新的钩子。
The hope here, is that we can take out some of the painful bits of the process and immediately get productive with our custom hook. Don’t worry though, I’ll explain what’s going on along the way.
这里的希望是,我们可以消除该过程中的一些痛苦工作,并立即使用我们的自定义钩子提高生产力。 不过请放心,我将解释整个过程。
The requirements here are git and yarn as it helps provide tools that make it easy to scaffold this template, such as using the workspaces feature to allow easy npm scripts to manage the code from the root of the project. If either of those are a dealbreaker, you can try downloading the repo via the download link and update it as needed.
这里的要求是git和yarn,因为它有助于提供使框架易于搭建的工具,例如使用工作区功能允许简单的npm脚本从项目根目录管理代码。 如果其中任何一个都是破坏交易的东西,您可以尝试通过下载链接下载存储库,然后根据需要进行更新。
从git克隆钩子模板 (Cloning the hook template from git)
To start, let’s clone the repository from Github. In the command below, you should replace use-my-custom-hook
with the name of your hook, such as use-cookies
or use-mooncake
.
首先,让我们从Github克隆存储库。 在下面的命令中,应use-my-custom-hook
的名称替换use-my-custom-hook
hook,例如use-cookies
或use-mooncake
。
git clone https://github.com/colbyfayock/use-custom-hook use-my-custom-hook
cd use-my-custom-hook
Once you clone and navigate to that folder, you should now see 2 directories – an example
directory and a use-custom-hook
directory.
克隆并导航到该文件夹后,您现在应该看到2个目录- example
目录和use-custom-hook
目录。
This will give you a few things to get started:
这将为您提供一些入门知识:
- A hook directory that will include the source for our hook 一个钩子目录,其中将包含我们的钩子源
Build scripts that compile our hook with babel
建立使用babel编译我们的钩子的脚本
An example page that imports our hook and creates a simple demo page with next.js
导入我们的钩子并使用next.js创建一个简单演示页面的示例页面
运行挂钩设置脚本 (Running the hook setup scripts)
After we successfully clone the repo, we want to run the setup scripts which install dependencies and update the hook to the name we want.
成功克隆存储库后,我们要运行安装脚本来安装依赖项并将钩子更新为所需的名称。
yarn install && yarn setup
When the setup script runs, it will do a few things:
安装脚本运行时,它将执行以下操作:
- It will ask you for your name – this is used to update the LICENSE and the package's author name 它将询问您的姓名-用于更新许可证和软件包的作者姓名
- It will ask you for your hook's name in 2 variations – camelCase and snake-case - this will be used to update the name of the hook throughout the template and move files with that name to the correct location 它将在两个变体中要求您提供钩子的名称-camelCase和snake-case-这将用于在整个模板中更新钩子的名称,并将具有该名称的文件移动到正确的位置
- It will reset git – it will first remove the local .git folder, which contains the history from my template and reinitialize git with a fresh commit to start your new history in 它将重置git –首先将删除本地.git文件夹,该文件夹包含我模板中的历史记录,并使用新的提交重新初始化git以在其中开始新的历史记录
- Finally, it will remove the setup script directory and remove the package dependencies that were only being used by those scripts 最后,它将删除安装脚本目录并删除那些脚本仅使用的软件包依赖项
启动开发服务器 (Starting the development server)
Once the setup scripts finish running, you'll want to run:
安装脚本完成运行后,您将需要运行:
yarn develop
This runs a watch process on the hook source, building the hook locally each time a source file is changed, and running the example app server, where you can test the hook and make changes to the example pages.
这将在挂钩源上运行监视过程,每次更改源文件时都在本地构建挂钩,然后运行示例应用程序服务器,您可以在其中测试挂钩并更改示例页面。
With this all ready, we can get started!
一切准备就绪,我们就可以开始!
第2步:编写新的React Hook (Step 2: Writing your new React Hook)
At this point, you should now have a new custom hook where you can make it do whatever you'd like. But since we're going to walk through rebuilding the usePlaceCage hook, let's start there.
此时,您现在应该有了一个新的自定义钩子,可以在其中使其随心所欲。 但是,由于我们将逐步重建usePlaceCage挂钩,因此让我们从这里开始。
The usePlaceCage hook does 1 simple thing from a high level view – it takes in a configuration object and returns a number of image URLs that you can then use for your app.
usePlaceCage挂钩从高层次的视图中完成了一件简单的事情-它接受一个配置对象,并返回许多图像URL,然后您可以将它们用于您的应用程序。
Just as a reminder, any time I mention usePlaceCage
or use-placecage
, you should use the hook name that you set up before.
提醒一下,每当我提到usePlaceCage
或use-placecage
,都应使用之前设置的钩子名称。
关于placecage.com的一点点 (A little bit about placecage.com)
Placecage.com is a placeholder image service that does 1 thing. It takes a URL with a simple configuration and returns an image... of Nic Cage.
Placecage.com是一个占位符图像服务,可做1件事。 它采用简单配置的URL并返回Nic Cage的图像。
From the simplest use, the service uses a URL pattern as follows:
从最简单的用途来看,该服务使用如下URL模式:
https://www.placecage.com/200/300
This would return an image with a width of 200 and height of 300.
这将返回宽度为200,高度为300的图像。
Optionally, you can pass an additional URL parameter that defines the type of image:
(可选)您可以传递定义图像类型的附加URL参数:
https://www.placecage.com/gif/200/300
In this particular instance, our type is gif
, so we'll receive a gif.
在这种情况下,我们的类型是gif
,因此我们将收到一个gif。
The different types available to use are:
可用的不同类型是:
- Nothing: calm 没事:冷静
g
: grayg
:灰色c
: crazyc
:疯了gif
: gifgif
:gif
We'll use this to define how we set up configuration for our hook.
我们将使用它来定义如何为钩子设置配置。
定义我们的核心生成器功能 (Defining our core generator function)
To get started, we're going to copy over a function at the bottom of our use-placecage/src/usePlaceCage.js
file, which allows us to generate an image URL, as well as a few constant definitions that we'll use in that function.
首先,我们将复制一个use-placecage/src/usePlaceCage.js
文件底部的函数,该函数允许我们生成图像URL以及一些将要使用的常量定义在那个功能。
First, let's copy over our constants to the top of our usePlaceCage.js
file:
首先,让我们将常量复制到usePlaceCage.js
文件的顶部:
const PLACECAGE_HOST = 'https://www.placecage.com/';
const TYPES = {
calm: null,
gray: 'g',
crazy: 'c',
gif: 'gif'
};
const DEFAULT_TYPE = 'calm';
const ERROR_BASE = 'Failed to place Nick';
Here we:
在这里,我们:
- Define a host, which is the base URL of our image service. 定义一个主机,这是我们图像服务的基本URL。
Define the available types, which we'll use in the configuration API. We set
calm
tonull
, because it's the default value which you get by not including it at all定义可用的类型,我们将在配置API中使用这些类型。 我们将
calm
设置为null
,因为这是您根本不包含它的默认值Our default type will be
calm
我们的默认类型将是
calm
- And we set an error base which is a consistent message when throwing an error 并且我们设置了一个错误基准,它是抛出错误时的一致消息
Then for our function, let's copy this at the bottom of our usePlaceCage.js
file:
然后,对于我们的功能,让我们将其复制到usePlaceCage.js
文件的底部:
function generateCage(settings) {
const { type = DEFAULT_TYPE, width = 200, height = 200, count = 1 } = settings;
const config = [];
if ( type !== DEFAULT_TYPE && TYPES[type] ) {
config.push(TYPES[type]);
}
config.push(width, height);
if ( isNaN(count) ) {
throw new Error(`${ERROR_BASE}: Invalid count ${count}`);
}
return [...new Array(count)].map(() => `${PLACECAGE_HOST}${config.join('/')}`);
}
Walking through this code:
遍历这段代码:
We define a
generateCage
function which we'll use to generate our image URL我们定义了
generateCage
函数,我们将使用该函数来生成图像URL- We take in a settings object as an argument, which defines the configuration of our image URL. We'll be using the same parameters as we saw in our placecage.com URL 我们以设置对象作为参数,它定义了图像URL的配置。 我们将使用与在placecage.com URL中看到的相同的参数
- We destructure those settings to make them available for us to use 我们对这些设置进行解构以使它们可供我们使用
We have a few defaults here just to make it easier. Our default
type
will be defined byDEFAULT_TYPE
along with a default width, height, and number of results we want to return我们在这里有一些默认设置只是为了使其更容易。 我们的默认
type
将由DEFAULT_TYPE
定义,以及我们要返回的默认宽度,高度和结果数We create a
config
array. We'll use this to append all of the different configuration objects in our URL and finally join them together with a/
essentially making a URL我们创建一个
config
数组。 我们将使用它在我们的URL中附加所有不同的配置对象,最后将它们与/
结合在一起,从而构成一个URLBefore we push our config to that array, we check if it's a valid argument, by using the
TYPES
object to check against it. If it's valid, we push it to our config array在将配置推送到该数组之前,我们使用
TYPES
对象检查它是否是有效参数。 如果有效,我们将其推送到配置数组- We then push our width and height 然后我们推我们的宽度和高度
We do some type checking, if we don't have a valid number as the
count
, we throw an error, otherwise we'll get incorrect results我们进行一些类型检查,如果没有有效的数字作为
count
,则抛出错误,否则将得到错误的结果Finally, we return a new array with the number of results requested, mapped to a URL creator, which uses
PLACECAGE_HOST
as our defined base URL, and with our config array joined by/
最后,我们返回一个新数组,其中包含请求的结果数,并映射到URL创建器,该创建器使用
PLACECAGE_HOST
作为定义的基本URL,并在配置数组中添加/
And if we were to test this function, it would look like this:
如果我们要测试此功能,它将看起来像这样:
const cage = generateCage({
type: 'gif',
width: 500,
height: 500,
count: 2
});
console.log(cage); // ['https://www.placecage.com/gif/500/500', 'https://www.placecage.com/gif/500/500']
在钩子中使用我们的功能 (Using our function in the hook)
So now that we have our generator function, let's actually use it in our hook!
因此,既然我们有了生成器函数,就可以在钩子中实际使用它了!
Inside of the usePlaceCage
function in the use-placecage/src/usePlaceCage.js
file, we can add:
在use-placecage/src/usePlaceCage.js
文件的usePlaceCage
函数内部,我们可以添加:
export default function usePlaceCage (settings = {}) {
return generateCage(settings);
}
What this does it uses our generator function, takes in the settings that were passed into the hook, and returns that value from the hook.
它的作用是使用生成器函数,接受传递到挂钩中的设置,然后从挂钩中返回该值。
Similar to our previous use example, if we were to use our hook, it would look like this:
与我们先前的使用示例类似,如果要使用钩子,它将看起来像这样:
const cage = usePlaceCage({
type: 'gif',
width: 500,
height: 500,
count: 2
});
console.log(cage); // ['https://www.placecage.com/gif/500/500', 'https://www.placecage.com/gif/500/500']
At this point, it does the same thing!
在这一点上,它做同样的事情!
So now we have our hook, it serves as a function to generate image URLs for the placecage.com service. How can we actually use it?
因此,现在有了钩子,它可以用作为placecage.com服务生成图像URL的功能。 我们如何实际使用它?
第3步:在示例中使用React钩子 (Step 3: Using your React hook in an example)
The good news about our template, is it already includes an example app that we can update to easily make use of our hook to both test and provide documentation for those who want to use it.
关于模板的好消息是,它已经包含了一个示例应用程序,我们可以对其进行更新,以轻松利用我们的钩子为想要使用它的人测试并提供文档。
设置挂钩 (Setting up the hook)
To get started, let's open up our example/pages/index.js
file. Inside of this file you'll see the following:
首先,让我们打开example/pages/index.js
文件。 在此文件内,您将看到以下内容:
const hookSettings = {
message: 'Hello, custom hook!'
}
const { message } = usePlaceCage(hookSettings);
This snippet is what was used by default in the template just for a proof of concept, so let's update that. We're going to use the same exact configuration as we did in Step 2:
默认情况下,此代码段是模板中使用的代码,仅用于概念证明,因此让我们对其进行更新。 我们将使用与步骤2完全相同的配置:
const hookSettings = {
type: 'gif',
width: 500,
height: 500,
count: 2
}
const cage = usePlaceCage(hookSettings);
Again, we set up our settings object with the configuration for our hook and invoke our hook and set the value to the cage
constant.
同样,我们使用钩子的配置来设置设置对象,并调用钩子并将其值设置为cage
常量。
If we now console log that value our to our dev tools, we can see it working!
如果现在通过控制台日志对我们的开发工具有价值,那么我们可以看到它正在工作!
console.log('cage', cage);
Note: If you get an error here about message
, you can comment that our or remove it under the Examples section.
注意:如果您在此处收到有关message
的错误,则可以在“示例”部分中对其进行评论或将其删除。
使用我们的新钩子配置更新示例 (Updating the example with our new hook configuration)
If you scroll down to the Examples section, you'll notice that we have the same default hookSettings
as above, so let's update that again to make sure our example is accurate.
如果向下滚动到“示例”部分,您会注意到我们具有与上面相同的默认hookSettings
,因此让我们再次对其进行更新以确保我们的示例正确。
{`const hookSettings = {
type: 'gif',
width: 500,
height: 500,
count: 2
}
const cage = usePlaceCage(hookSettings);`}
You'll also notice that we're no longer using the message
variable. If you didn't remove it in the last step, we can now replace it under the Output heading with:
您还会注意到,我们不再使用message
变量。 如果您没有在最后一步中将其删除,我们现在可以在Output标题下将其替换为:
<p>
{ JSON.stringify(cage) }
</p>
<p>
{ cage.map((img, i) => <img key={`img-${i}`} width={200} src={img} />)}
</p>
We're doing 2 things here:
我们在这里做两件事:
Instead of showing the variable itself, we wrap it with
JSON.stringify
so that we can show the contents of the array我们没有显示变量本身,而是用
JSON.stringify
包裹它,以便可以显示数组的内容。We also use the
map
function to loop over our image URLs in thecage
constant and create a new image element for each. This let's us preview the output instead of just seeing the values我们还使用
map
函数在cage
常量中循环我们的图像URL,并为每个URL创建一个新的图像元素。 让我们预览输出,而不只是看值
And once you save and open your browser, you should now see your updated examples and output!
保存并打开浏览器后,您现在应该看到更新的示例和输出!
您可以在该页面上执行的其他操作 (Other things you can do on that page)
Before moving on, you can also update a few other things that will be important for your hooks page:
在继续之前,您还可以更新其他一些对于钩子页面很重要的事情:
Update the How to use section with instructions
使用说明更新“ 使用方法”部分
- Add additional examples to make it easier for people to know what to do 添加其他示例,使人们更容易知道该怎么做
A few things are also automatically pulled in from the use-placecage/package.json
file. You can either update them there to make it easier to maintain or you can replace them in the example page:
一些事情也会自动从use-placecage/package.json
文件中use-placecage/package.json
。 您可以在那里进行更新以使其易于维护,也可以在示例页面中替换它们:
name
: Is used at the<h1>
of the pagename
:在页面的<h1>
中使用description
: Is used at the description under the<h1>
description
:用于<h1>
下的描述repository.url
: Used to include a link to the repositoryrepository.url
:用于包括到存储库的链接author
: Thename
andurl
are used to include a link at the bottom of the pageauthor
:name
和url
用于在页面底部添加一个链接
步骤4:编译您的React钩子和示例 (Step 4: Compiling your React hook and Example)
The way we can make our hook work easily as an npm module is to compile it for others to use. We're using babel to do this.
我们可以使钩子作为npm模块轻松工作的方法是对其进行编译以供其他人使用。 我们正在使用babel来做到这一点。
Though the publish process already does this for us automatically with the prepublishOnly
script in use-placecage/package.json
, we can manually compile our hook using the yarn build
command from the root of the project.
虽然发布过程已经与这确实为我们自动prepublishOnly
在脚本中use-placecage/package.json
,我们可以使用手动编译我们的钩yarn build
命令,从项目的根目录。
Along with compiling the hook, running yarn build
will also compile the example page, allowing you to upload it wherever you'd like. After running that command, you should see an output of static HTML files in the example/out
directory.
除了编译钩子,运行yarn build
还将编译示例页面,使您可以将其上载到任何位置。 运行该命令后,您应该在example/out
目录中看到静态HTML文件的输出。
If you're looking for a recommendation, Netlify makes it easy to connect your Github account and deploy the static site.
如果您正在寻找建议, Netlify可让您轻松连接Github帐户并部署静态站点。
See the demo site deployed to Netlify!
第5步:将React钩子发布到npm (Step 5: Publishing your React hook to npm)
Finally, if you're happy with your hook, it's time to publish!
最后,如果您对自己的钩子感到满意,就该发布了!
npm makes this part really easy. The only prerequisite you need to have an npm account. With that account, let's log in:
npm使这部分变得非常容易。 您需要拥有npm帐户的唯一前提条件。 使用该帐户,我们登录:
npm login
Which will prompt you for your login credentials.
它将提示您输入登录凭据。
Next, let's navigate to our hook's directory, as our package configuration is there under use-placecage/package.json
:
接下来,让我们导航到钩子的目录,因为我们的包配置位于use-placecage/package.json
:
cd use-placecage
Then, we can simply publish!
然后,我们可以简单地发布!
npm publish
Keep in mind, that each package name needs to be unique. If you used use-placecage
, it's already taken... by me. 😃
请记住,每个程序包名称都必须唯一。 如果您使用过use-placecage
,那么它已经被我拿走了。 😃
But if you're successful, npm should build your hook and upload it to the package registry!
但是,如果成功,npm应该建立您的钩子并将其上传到软件包注册表!
It will then be available on npm with the following pattern:
然后它将以以下模式在npm上可用:
https://www.npmjs.com/package/[package-name]
So for use-placeage
, it's available here: https://www.npmjs.com/package/use-placecage
所以对于use-placeage
,可以在这里找到: https : use-placeage
现在,我们有了一个自定义钩子! (We now have a custom hook!)
Yay 🎉 if you followed along, you should now have created a custom hook and published it to npm.
Yay🎉如果您继续这样做,您现在应该已经创建了一个自定义钩子并将其发布到npm。
Though this was a silly example using placecage.com, it gives us a good idea of how we can easily set this up.
尽管这是使用placecage.com的愚蠢示例,但它使我们对如何轻松设置它有了一个很好的了解。
You'll also notice that this specific example wasn't the best use case for a hooks, where we could have simply used a function. Typically, we'll want to use custom hooks to wrap functionality that can only live inside a React component, such as useState
. To learn more about that, you can read one of my other articles about custom hooks.
您还将注意到,这个特定示例并不是钩子的最佳用例,我们可以仅使用一个函数。 通常,我们希望使用自定义钩子来包装只能存在于React组件内部的功能,例如useState
。 要了解更多信息,您可以阅读我的其他有关自定义钩子的文章之一。
However, this gave us a good basis to talk through the creation and configuration of our new hook!
但是,这为我们提供了一个很好的基础来讨论新钩子的创建和配置!
有关钩子的更多资源 (More resources about hooks)
How to destructure the fundamentals of React Hooks (freecodecamp.org)
如何破坏React Hooks的基础知识 (freecodecamp.org)
Introducing Hooks (reactjs.org)
挂钩介绍 (reactjs.org)
Hooks API Reference (reactjs.org)
Hooks API参考 (reactjs.org)
翻译自: https://www.freecodecamp.org/news/how-to-create-a-custom-react-hook-and-publish-it-to-npm/
npm创建react项目