Sådan oprettes en brugerdefineret reaktorkrog og offentliggør den til npm

Kroge er en praktisk tilføjelse til React API, der giver os mulighed for at organisere nogle af vores logik og tilstand i funktionskomponenter. Hvordan kan vi bygge en brugerdefineret krog og dele den med resten af ​​verden?

  • Hvad er kroge?
  • Hvorfor er brugerdefinerede kroge seje?
  • Hvad skal vi lave?
  • Trin 0: Navngiv din krog
  • Trin 1: Opsætning af dit projekt
  • Trin 2: Skriv din nye React Hook
  • Trin 3: Brug din React-krog i et eksempel
  • Trin 4: Kompilering af din React-krog og eksempel
  • Trin 5: Udgivelse af din React-krog til npm
  • Flere ressourcer om kroge

Hvad er kroge?

Reager kroge i enkle vendinger er funktioner. Når du inkluderer dem i din komponent eller i en anden krog, giver de dig mulighed for at gøre brug af React-interner og dele af React-livscyklussen med native kroge som useStateog useEffect.

Jeg planlægger ikke at lave et dybt dyk om kroge, men du kan tjekke en hurtig introduktion med et eksempel på useStatesåvel som introduktionen fra React-teamet.

Hvorfor er brugerdefinerede kroge seje?

Det fantastiske ved at oprette brugerdefinerede kroge er, at de giver dig mulighed for at abstrakte logik for dine komponenter, hvilket gør det lettere at genbruge på tværs af flere komponenter i din app.

For eksempel, hvis du vil oprette en simpel tæller, hvor du bruger React's tilstand til at styre det aktuelle antal. I stedet for at have den samme useStatekrog i hver komponentfil kan du oprette denne logik en gang i en useCounterkrog, hvilket gør det lettere at vedligeholde, udvide og squash bugs, hvis de kommer op.

Hvad skal vi lave?

Med henblik på denne artikel vil vi holde det simpelt med en grundlæggende krog. Normalt bruger du muligvis en krog, fordi du i stedet for en typisk funktion bruger andre native kroge, der skal bruges inden for React-funktionskomponenter. Vi holder fast ved nogle grundlæggende input og output for at holde tingene enkle.

Vi vil genskabe denne brugerdefinerede Placecage-krog, jeg lavede, der giver dig mulighed for nemt at generere billed-URL'er, som du kan bruge som pladsholderbilleder.

Hvis du ikke kender, er Placecage en API, der giver dig mulighed for at generere billeder af Nic Cage som pladsholderbilleder til dit websted. Fjollet? Ja. Sjovt? Absolut!

Men hvis du ikke er fan af Nic's arbejde, kan du lige så let bytte URL-adressen til Fill Murray, der bruger billeder af Bill Murray eller placeholder.com, som genererer en simpel baggrundsfarve med tekst, der viser billedets størrelse.

Trin 0: Navngiv din krog

Før vi hopper ind i vores faktiske kode, er vores ultimative mål at udgive denne krog. Hvis det ikke er dit mål, kan du springe dette trin over, men til udgivelse vil vi oprette et navn til vores krog.

I vores tilfælde vil vores krognavn være usePlaceCage. Nu med det i tankerne har vi to formater af vores navn - et i camelCase-format og et i slangesagformat.

  • camelCase: usePlaceCage
  • slangetaske : brug-placecage

CamelCase-formatet vil blive brugt til den aktuelle krogfunktion, hvor slangesagens navn vil blive brugt til pakkenavnet og nogle af mapperne. Når du opretter navnet, skal du huske på, at pakkens navn skal være unikt. Hvis der allerede findes en pakke med samme navn på npmjs.com, kan du ikke bruge den.

Hvis du ikke allerede har et navn, er det okay! Du kan bare bruge dit eget navn eller noget du kan tænke på, det betyder ikke rigtig noget for meget, da vi virkelig bare prøver at lære at gøre dette. Hvis det for eksempel var mig, ville jeg bruge:

  • camelCase: useColbysCoolHook
  • slangetaske : brug-colbyscoolhook

Men bare for at præcisere, for resten af ​​vores eksempel, skal vi holde os til usePlaceCageog use-placecage.

Trin 1: Opsætning af dit projekt

Selvom du kan oprette dit projekt, men du vil, går vi igennem og bygger en ny krog fra denne skabelon, jeg oprettede.

Håbet her er, at vi kan fjerne nogle af de smertefulde bits i processen og straks blive produktive med vores brugerdefinerede krog. Bare rolig, men jeg forklarer, hvad der foregår undervejs.

Kravene her er git og garn, da det hjælper med at levere værktøjer, der gør det let at stilladser denne skabelon, f.eks. Ved hjælp af arbejdsrumsfunktionen, så let npm-scripts kan styre koden fra projektets rod. Hvis en af ​​disse er en dealbreaker, kan du prøve at downloade repoen via downloadlinket og opdatere det efter behov.

Kloning af krogskabelonen fra git

For at starte, lad os klone lageret fra Github. I kommandoen nedenfor skal du erstatte use-my-custom-hookmed navnet på din krog, såsom use-cookieseller use-mooncake.

git clone //github.com/colbyfayock/use-custom-hook use-my-custom-hook cd use-my-custom-hook 

Når du har klonet og navigeret til den mappe, skal du nu se 2 mapper - en examplemappe og en use-custom-hookmappe.

Dette giver dig et par ting at komme i gang:

  • En krokatalog, der inkluderer kilden til vores krog
  • Byg scripts, der sammensætter vores krog med babel
  • En eksempelside, der importerer vores krog og opretter en simpel demoside med next.js

Kørsel af krogopsætningsskripter

Når vi har klonet repoen med succes, vil vi køre installationsscripts, der installerer afhængigheder og opdatere krogen til det navn, vi ønsker.

yarn install && yarn setup 

Når installationsscriptet kører, vil det gøre et par ting:

  • 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
  • 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
  • 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!

Follow along with the commit!

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.

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.

Just as a reminder, any time I mention usePlaceCage or use-placecage, you should use the hook name that you set up before.

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.

From the simplest use, the service uses a URL pattern as follows:

//www.placecage.com/200/300 

This would return an image with a width of 200 and height of 300.

Optionally, you can pass an additional URL parameter that defines the type of image:

//www.placecage.com/gif/200/300 

In this particular instance, our type is gif, so we'll receive a gif.

The different types available to use are:

  • Nothing: calm
  • g: gray
  • c: crazy
  • gif: 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.

First, let's copy over our constants to the top of our usePlaceCage.js file:

const PLACECAGE_HOST = '//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.
  • Define the available types, which we'll use in the configuration API. We set calm to null, because it's the default value which you get by not including it at all
  • Our default type will be 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:

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
  • 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
  • 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 by DEFAULT_TYPE along with a default width, height, and number of results we want to return
  • 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
  • Before 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
  • 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
  • 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 /

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); // ['//www.placecage.com/gif/500/500', '//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:

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); // ['//www.placecage.com/gif/500/500', '//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?

Follow along with the commit!

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:

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:

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.

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.

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.

{`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:

{ JSON.stringify(cage) }

{ cage.map((img, i) =>)}

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
  • We also use the map function to loop over our image URLs in the cage constant and create a new image element for each. This let's us preview the output instead of just seeing the values

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:

  • name: Is used at the

    of the page

  • description: Is used at the description under the

  • repository.url: Used to include a link to the repository
  • author: The name and url are used to include a link at the bottom of the page

Follow along with the commit!

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.

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.

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.

If you're looking for a recommendation, Netlify makes it easy to connect your Github account and deploy the static site.

See the demo site deployed to Netlify!

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 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:

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. ?

But if you're successful, npm should build your hook and upload it to the package registry!

It will then be available on npm with the following pattern:

//www.npmjs.com/package/[package-name] 

So for use-placeage, it's available here: //www.npmjs.com/package/use-placecage

We now have a custom hook!

Yay ? if you followed along, you should now have created a custom hook and published it to npm.

Though this was a silly example using placecage.com, it gives us a good idea of how we can easily set this up.

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.

However, this gave us a good basis to talk through the creation and configuration of our new hook!

Flere ressourcer om kroge

  • Sådan ødelægges det grundlæggende i React Hooks (freecodecamp.org)
  • Introduktion til kroge (reactjs.org)
  • Hooks API Reference (reactjs.org)

Følg mig for mere Javascript, UX og andre interessante ting!

  • ? Følg mig på Twitter
  • ? ️ Abonner på min Youtube
  • ✉️ Tilmeld dig mit nyhedsbrev