Giter Club home page Giter Club logo

bookshelf's Introduction

Building a full React application

The React and JavaScript ecosystem is full of tools and libraries to help you build your applications. In this (huge) workshop we’ll build an application from scratch using widely supported and proven tools and techniques. We’ll cover everything about building frontend React applications, from the absolute basics to the tricky parts you'll run into building real world React apps and how to create great abstractions.

Learn React from Start to Finish

Build Status All Contributors GPL 3.0 License Code of Conduct

Prerequisites

  • You'll want experience with React before going through this material. The lessons get progressively more advanced. Once you hit something you're unfamiliar with, that's your cue to go back and review the other parts of EpicReact.Dev.

NOTE: The EpicReact.dev videos were recorded with React version ^16.13 and all material in this repo has been updated to React version ^18. Differences are minor and any relevant differences are noted in the instructions.

System Requirements

All of these must be available in your PATH. To verify things are set up properly, you can run this:

git --version
node --version
npm --version

If you have trouble with any of these, learn more about the PATH environment variable and how to fix it here for windows or mac/linux.

Demo

Hosted on https://bookshelf.lol

Setup

If you want to commit and push your work as you go, you'll want to fork first and then clone your fork rather than this repo directly.

After you've made sure to have the correct things (and versions) installed, you should be able to just run a few commands to get set up:

git clone https://github.com/kentcdodds/bookshelf.git
cd bookshelf
node setup

This may take a few minutes.

If you get any errors, please read through them and see if you can find out what the problem is. If you can't work it out on your own then please file an issue and provide all the output from the commands you ran (even if it's a lot).

If you can't get the setup script to work, then just make sure you have the right versions of the requirements listed above, and run the following commands:

npm install
npm run validate

If you are still unable to fix issues and you know how to use Docker 🐳 you can setup the project with the following command:

docker-compose up

It's recommended you run everything locally in the same environment you work in every day, but if you're having issues getting things set up, you can also set this up using GitHub Codespaces (video demo) or Codesandbox.

Running the app

To get the app up and running (and really see if it worked), run:

npm start

This should start up your browser. If you're familiar, this is a standard react-scripts application.

You can also open the production deployment: bookshelf.lol.

Running the tests

npm test

This will start Jest in watch mode. Read the output and play around with it. The tests are there to help you reach the final version, however sometimes you can accomplish the task and the tests still fail if you implement things differently than I do in my solution, so don't look to them as a complete authority.

Working through the exercises

To get started, run:

node go

This will allow you to choose which exercise you want to work on. From there, open the INSTRUCTIONS.md file and follow the instructions.

If you'd like to work on an extra credit, but you want to skip the preceding steps, you can run node go again:

node go

This will let you choose the next exercise or you can choose which part of the exercise you'd like to work on. This will update your exercise files to the correct version for you to work on that extra credit.

Exercises

The exercises are in different branches. Each branch changes the INSTRUCTIONS.md file to contain instructions you need to complete the exercise.

The purpose of the exercise is not for you to work through all the material. It's intended to get your brain thinking about the right questions to ask me as I walk through the material.

Helpful Emoji 🐨 πŸ’° πŸ’― πŸ“ πŸ¦‰ πŸ“œ πŸ’£ πŸ’ͺ 🏁 πŸ‘¨β€πŸ’Ό 🚨

Each exercise has comments in it to help you get through the exercise. These fun emoji characters are here to help you.

  • Kody the Koala 🐨 will tell you when there's something specific you should do version
  • Marty the Money Bag πŸ’° will give you specific tips (and sometimes code) along the way
  • Hannah the Hundred πŸ’― will give you extra challenges you can do if you finish the exercises early.
  • Nancy the Notepad πŸ“ will encourage you to take notes on what you're learning
  • Olivia the Owl πŸ¦‰ will give you useful tidbits/best practice notes and a link for elaboration and feedback.
  • Dominic the Document πŸ“œ will give you links to useful documentation
  • Berry the Bomb πŸ’£ will be hanging around anywhere you need to blow stuff up (delete code)
  • Matthew the Muscle πŸ’ͺ will indicate that you're working with an exercise
  • Chuck the Checkered Flag 🏁 will indicate that you're working with a final
  • Peter the Product Manager πŸ‘¨β€πŸ’Ό helps us know what our users want
  • Alfred the Alert 🚨 will occasionally show up in the test failures with potential explanations for why the tests are failing.

Workflow

  • Checkout the exercise branch
  • Read through the INSTRUCTIONS.md
  • Start exercise
  • Go through every mentioned file and follow the instructions from the emoji
  • We all come back together
  • I go through the solution and answer questions
  • Move on to the next exercise.
  • Repeat.

App Data Model

  • User

    • id: string
    • username: string
  • List Item

    • id: string
    • bookId: string
    • ownerId: string
    • rating: number (-1 is no rating, otherwise it's 1-5)
    • notes: string
    • startDate: number (Date.now())
    • finishDate: number (Date.now())

For convenience, our friendly backend engineers also return a book object on each list item which is the book it's associated to. Thanks backend folks!

/me wishes we could use GraphQL

If your "database" gets out of whack, you can purge it via:

window.__bookshelf.purgeUsers()
window.__bookshelf.purgeListItems()
  • Book

    • id: string
    • title: string
    • author: string
    • coverImageUrl: string
    • pageCount: number
    • publisher: string
    • synopsis: string

Troubleshooting

Running "node go" does not list any branches

This means there was something wrong when you ran the setup. Try running:

node ./scripts/track-branches.js

If you're still not getting the branches, then you can do this manually:

git branch --track "exercises/01-bootstrap" "origin/exercises/01-bootstrap"
git branch --track "exercises/02-styles" "origin/exercises/02-styles"
git branch --track "exercises/03-data-fetching" "origin/exercises/03-data-fetching"
git branch --track "exercises/04-authentication" "origin/exercises/04-authentication"
git branch --track "exercises/05-routing" "origin/exercises/05-routing"
git branch --track "exercises/06-cache-management" "origin/exercises/06-cache-management"
git branch --track "exercises/07-context" "origin/exercises/07-context"
git branch --track "exercises/08-compound-components" "origin/exercises/08-compound-components"
git branch --track "exercises/09-performance" "origin/exercises/09-performance"
git branch --track "exercises/10-render-as-you-fetch" "origin/exercises/10-render-as-you-fetch"
git branch --track "exercises/11-unit-testing" "origin/exercises/11-unit-testing"
git branch --track "exercises/12-testing-hooks-and-components" "origin/exercises/12-testing-hooks-and-components"
git branch --track "exercises/13-integration-testing" "origin/exercises/13-integration-testing"
git branch --track "exercises/14-e2e-testing" "origin/exercises/14-e2e-testing"

git pull --all

Contributors

Thanks goes to these wonderful people (emoji key):

Kent C. Dodds
Kent C. Dodds

πŸ’» πŸ“– πŸš‡ ⚠️
Vojta Holik
Vojta Holik

🎨 πŸ’»
Richard B. Kaufman-LΓ³pez
Richard B. Kaufman-LΓ³pez

πŸ’»
Sekib Omazic
Sekib Omazic

πŸ“–
Justin Dorfman
Justin Dorfman

πŸ”
Nash Kabbara
Nash Kabbara

πŸ“– πŸ’» πŸ›
UMAIR MOHAMMAD
UMAIR MOHAMMAD

πŸ’»
onemen
onemen

πŸ’»
Artem Zakharchenko
Artem Zakharchenko

πŸ’»
Leonardo Elias
Leonardo Elias

πŸ’»
Oluwaseun Oyebade
Oluwaseun Oyebade

πŸ›
Wes Bos
Wes Bos

πŸ€”
Jesse Jafa
Jesse Jafa

πŸ€”
Huy Dang
Huy Dang

πŸ›
Gabriel Abud
Gabriel Abud

πŸ“–
Kody Clemens
Kody Clemens

πŸ“–
calec
calec

πŸ“–
Emmanouil Zoumpoulakis
Emmanouil Zoumpoulakis

πŸ’»
Christian Schurr
Christian Schurr

πŸ’» πŸ›
Bob Massarczyk
Bob Massarczyk

πŸ“–
Deepak Chandani
Deepak Chandani

πŸ’»
Juliano Farias
Juliano Farias

⚠️
Robbert Wolfs
Robbert Wolfs

πŸ“– πŸ’»
komisz
komisz

πŸ›
MichaΓ«l De Boey
MichaΓ«l De Boey

πŸ“† πŸ’»
Marco Moretti
Marco Moretti

πŸ’»
Vasilii Kovalev
Vasilii Kovalev

πŸ’» πŸ“–
Peramanathan Sathyamoorthy
Peramanathan Sathyamoorthy

πŸ’»
William BEUIL
William BEUIL

πŸ’»
Andrew Li
Andrew Li

πŸ“–
Tony Khaov
Tony Khaov

πŸ“–
Stijn Geens
Stijn Geens

πŸ“–
AndrΓ©s Gallego
AndrΓ©s Gallego

πŸ€”
Michal JuriΕ‘
Michal JuriΕ‘

πŸ›
jkmuka
jkmuka

πŸ›
raqib-rasheed
raqib-rasheed

πŸ›
Luke-kb
Luke-kb

πŸ“–
Peter HozΓ‘k
Peter HozΓ‘k

πŸ’»
Chris Chuang
Chris Chuang

πŸ’» πŸ›
Valentin Hervieu
Valentin Hervieu

πŸ“–
~Sami Triki
~Sami Triki

πŸ“–
Ryan Boone
Ryan Boone

πŸ“–
Juan Latorre
Juan Latorre

πŸ›
Roch GoszczyΕ„ski
Roch GoszczyΕ„ski

πŸ’» πŸ›
Hendrik Mittrop
Hendrik Mittrop

πŸ’»
payapula
payapula

πŸ“–
Jelte Homminga
Jelte Homminga

πŸ“–
Omri Dagan
Omri Dagan

πŸ“–
Justin Domingue
Justin Domingue

πŸ“–
Marc-Antoine Ferland
Marc-Antoine Ferland

πŸ“–
Mario Sannum
Mario Sannum

πŸ’»
jansabbe
jansabbe

πŸ“–
Aswin
Aswin

πŸ“–
Iacopo Pazzaglia
Iacopo Pazzaglia

πŸ“–
Luciano Ayres
Luciano Ayres

πŸ“–
Sadi Kaya
Sadi Kaya

πŸ“–
Rowin HernΓ‘ndez
Rowin HernΓ‘ndez

πŸ“–
Arturo Pie
Arturo Pie

πŸ’»
Caleb Jasik
Caleb Jasik

πŸ“–
Server Khalilov
Server Khalilov

πŸ“–
Angad Sethi
Angad Sethi

πŸ“–
Mary
Mary

πŸ“–
Diego Cardoso
Diego Cardoso

πŸ“–
kmccoan
kmccoan

πŸ“–
Ehsan Tatasadi
Ehsan Tatasadi

πŸ“–
PM6
PM6

πŸ’»
benjaminmatthews
benjaminmatthews

πŸ“–
juliane nagao
juliane nagao

πŸ“–

This project follows the all-contributors specification. Contributions of any kind welcome!

Workshop Feedback

Each exercise has an Elaboration and Feedback link. Please fill that out after the exercise and instruction.

At the end of the workshop, please go to this URL to give overall feedback. Thank you!

bookshelf's People

Contributors

allcontributors[bot] avatar aprillion avatar aswinckr avatar b2m9 avatar benjaminmatthews avatar calec avatar emzoumpo avatar frontendwizard avatar hmttrp avatar iacopo87 avatar jacobparis avatar jdorfman avatar kentcdodds avatar kettanaito avatar kodyclemens avatar leonardoelias avatar luke-kb avatar marcosvega91 avatar marioleed avatar milamer avatar onemen avatar p10ns11y avatar sadikaya avatar sekibomazic avatar sparragus avatar umarmuhandis avatar umr55766 avatar vojtaholik avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bookshelf's Issues

Figure out why Node v10.13 fails on MacOS

https://github.com/kentcdodds/bookshelf/runs/1359994006

Relevant output:

FAIL src/__tests__/book-screen.js (13.298 s)
  ● Console

    console.error
      { status: 404, message: 'Book not found' }

      at node_modules/react-query/lib/core/query.js:385:30

    console.error
      { status: 404, message: 'No user with the id "3672606755"' }

      at node_modules/react-query/lib/core/query.js:385:30

  ● can create a list item for the book

    TestingLibraryElementError: Unable to find an element with the role "button" and name `/mark as read/i`

    Here are the available roles:

      button:

      Name "Logout":
      <button
        class="css-105y6wg-Button-AuthenticatedApp e1baol0z3"
      />

      Name "Add to list":
      <button
        aria-label="Add to list"
        class="css-bnousp-CircleButton-TooltipButton e1baol0z0"
        data-reach-tooltip-trigger=""
      />

      --------------------------------------------------
      navigation:

      Name "":
      <nav
        class="css-17vy10h-Nav"
      />

      --------------------------------------------------
      list:

      Name "":
      <ul
        class="css-11z6h0h-Nav"
      />

      --------------------------------------------------
      listitem:

      Name "":
      <li />

      Name "":
      <li />

      Name "":
      <li />

      --------------------------------------------------
      link:

      Name "Reading List":
      <a
        class="css-14cbamv-NavLink"
        href="/list"
      />

      Name "Finished Books":
      <a
        class="css-14cbamv-NavLink"
        href="/finished"
      />

      Name "Discover":
      <a
        class="css-14cbamv-NavLink"
        href="/discover"
      />

      --------------------------------------------------
      main:

      Name "":
      <main
        class="css-12ehlsl-AuthenticatedApp"
      />

      --------------------------------------------------
      img:

      Name "iusto modi eum book cover":
      <img
        alt="iusto modi eum book cover"
        class="css-194shf0-BookScreen"
        src="http://placeimg.com/640/480"
      />

      --------------------------------------------------
      heading:

      Name "iusto modi eum":
      <h1 />

      --------------------------------------------------

    <body>
      <div>
        <div
          class="css-1pz3cpr-AuthenticatedApp"
        >
          Reymundo_Sipes71
          <button
            class="css-105y6wg-Button-AuthenticatedApp e1baol0z3"
          >
            Logout
          </button>
        </div>
        <div
          class="css-1dchfq2-AuthenticatedApp"
        >
          <div
            class="css-1bxv0zk-AuthenticatedApp"
          >
            <nav
              class="css-17vy10h-Nav"
            >
              <ul
                class="css-11z6h0h-Nav"
              >
                <li>
                  <a
                    class="css-14cbamv-NavLink"
                    href="/list"
                  >
                    Reading List
                  </a>
                </li>
                <li>
                  <a
                    class="css-14cbamv-NavLink"
                    href="/finished"
                  >
                    Finished Books
                  </a>
                </li>
                <li>
                  <a
                    class="css-14cbamv-NavLink"
                    href="/discover"
                  >
                    Discover
                  </a>
                </li>
              </ul>
            </nav>
          </div>
          <main
            class="css-12ehlsl-AuthenticatedApp"
          >
            <div>
              <div
                class="css-fkyky9-BookScreen"
              >
                <img
                  alt="iusto modi eum book cover"
                  class="css-194shf0-BookScreen"
                  src="http://placeimg.com/640/480"
                />
                <div>
                  <div
                    class="css-1tpptxu-BookScreen"
                  >
                    <div
                      class="css-y9z24n-BookScreen"
                    >
                      <h1>
                        iusto modi eum
                      </h1>
                      <div>
                        <i>
                          Kristopher Gorczany
                        </i>
                        <span
                          class="css-nn5rmi-BookScreen"
                        >
                          |
                        </span>
                        <i>
                          Cartwright - Ebert
                        </i>
                      </div>
                    </div>
                    <div
                      class="css-1etzife-BookScreen"
                    >
                      <button
                        aria-label="Add to list"
                        class="css-bnousp-CircleButton-TooltipButton e1baol0z0"
                        data-reach-tooltip-trigger=""
                      >
                        <svg
                          fill="currentColor"
                          height="1em"
                          stroke="currentColor"
                          stroke-width="0"
                          viewBox="0 0 512 512"
                          width="1em"
                          xmlns="http://www.w3.org/2000/svg"
                        >
                          <path
                            d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm144 276c0 6.6-5.4 12-12 12h-92v92c0 6.6-5.4 12-12 12h-56c-6.6 0-12-5.4-12-12v-92h-92c-6.6 0-12-5.4-12-12v-56c0-6.6 5.4-12 12-12h92v-92c0-6.6 5.4-12 12-12h56c6.6 0 12 5.4 12 12v92h92c6.6 0 12 5.4 12 12v56z"
                          />
                        </svg>
                      </button>
                    </div>
                  </div>
                  <div
                    class="css-n6nwxy-BookScreen"
                  />
                  <br />
                  <p
                    class="css-mptbr-BookScreen"
                  >
                    Sequi est necessitatibus ab eius ea molestiae et amet iure. Repellat doloremque dolores reiciendis magnam mollitia incidunt ad assumenda expedita. Odio voluptate tempora. Voluptatem eligendi explicabo ut.
                  </p>
                </div>
              </div>
            </div>
          </main>
        </div>
      </div>
    </body>

      78 | 
      79 |   expect(
    > 80 |     screen.getByRole('button', {name: /mark as read/i}),
         |            ^
      81 |   ).toBeInTheDocument()
      82 |   expect(
      83 |     screen.getByRole('button', {name: /remove from list/i}),

      at Object.getElementError (node_modules/@testing-library/dom/dist/config.js:37:19)
      at args (node_modules/@testing-library/dom/dist/query-helpers.js:90:38)
      at args (node_modules/@testing-library/dom/dist/query-helpers.js:62:17)
      at getByRole (node_modules/@testing-library/dom/dist/query-helpers.js:106:19)
      at Object.<anonymous>.test (src/__tests__/book-screen.js:80:12)

I was able to reproduce this locally. Just didn't have time to investigate.

The easy solution is to upgrade your version of node πŸ€·β€β™‚οΈ But I technically support Node 10 so long as it's LTS, so I'd like to get this fixed.

Add Node 15.x support

$ node setup
▢️  Starting workshop setup...
      Running the following command: npx "https://gist.github.com/kentcdodds/bb452ffe53a5caa3600197e1d8005733" -q -- --no-autofill
    ▢️  Starting: System Validation
          Ensuring the correct versions of tools are installed on this computer.
          Running the following command: npx "https://gist.github.com/kentcdodds/abbc32701f78fa70298d444c2303b6d9"
There were errors validating the compatibility of this computer:

    This computer has [email protected] installed, but node@^10.13 || 12 || 14 is required. Please update node: https://nodejs.org


If you would like to just ignore this error, then feel free to do so and install dependencies as you normally would in "C:\Users\juanl\repos\bookshelf". Just know that things may not work properly if you do...
npm ERR! code 1
npm ERR! path C:\Users\juanl\repos\bookshelf
npm ERR! command failed
npm ERR! command C:\Windows\system32\cmd.exe /d /s /c workshop-computer-validator

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\juanl\AppData\Local\npm-cache\_logs\2021-02-17T17_26_45_891Z-debug.log
    🚨  Failure: System Validation. Please review the messages above for information on how to troubleshoot and resolve this issue.
npm ERR! code 1
npm ERR! path C:\Users\juanl\repos\bookshelf
npm ERR! command failed
npm ERR! command C:\Windows\system32\cmd.exe /d /s /c workshop-setup -q -- --no-autofill

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\juanl\AppData\Local\npm-cache\_logs\2021-02-17T17_26_45_945Z-debug.log

Error in "Context" section

Issue:
Can not login into Bookshelf app "exercises/07-context".

Reproduction:

Screenshot 2020-10-13 at 19 18 40

Please let me know if I overlooked on something... Thanks in advance for your kind reply

buildListItem always returns NaN as finishDate and E13C6 has a bug in test

Hey Kent I found two interessting bugs, that together make the test in exercise 13 work.

Generate List Items

In buildListItem, the call to faker.date.between uses a number as the startDate, but in contrast to the type definitions a number always leads to an invalid date and therefore a finishDate of NaN. (Date.parse is used in date.between)

This issue is also in the main branch and fixing this issue will make the next issue throw an error.

Exercise 13 (Integration Testing) Extra Credit 6

While testing can mark a list item as read the list item is updated in the DB, but the app is already rendered, therefore the updated list item will never be fetched.

Possible solutions:

  • We could refetch the query with the query key
  • Create the user, book, and listitem before the render call
  • Change the renderBookScreen function so that it will take overrides instead of replacements (but only create a list item if listItem is not null). As we test the book screen we will need a user and a book anyway.
async function renderBookScreen({user, book, listItem} = {}) {
  user = await loginAsUser(user)
  book = await booksDB.create(buildBook(book))
  if (listItem !== null) {
    listItem = await listItemsDB.create(buildListItem({...listItem, owner: user, book}))
  }
  ...
}

But all those changes will lead to the video Create Component-Specific Utility - Extra Credit Solution 06 to be incorrect.

On the Integration testing exercise, comment is suggesting to mock `/me` endpoint rather than `/bootstrap`

On the Exercise branch - exercises/13-integration-testing

The comment is suggesting to mock the old endpoint /me which has been actually replaced with /bootstrap endpoint in the previous modules.

However in the video and final solutions, we are only mocking the /bootstrap endpoint to return {user, listItems}.

bookshelf

url ends with /me: respond with {user}
should be changed to
url ends with /bootstrap: respond with {user, listItems: []}

Profile in production and send to grafana

In my performance workshop I show people how to do React Production Performance Monitoring and explain that you'd normally send the data to a monitoring tool like Grafana, but I think it would help a lot if they saw an example of this.

So I'd like to set that up for this app, but I don't know how to get that set up/host it/load in data/make charts/etc. Happy to use Netlify functions to interact with it (if I can't do so direct from the client).

Anyone wanna help with this? I'm very out of my element here 😬

Optional chain operator syntax throwing eslint error.

Description

Hey Kent

Having an issue with the optional chaining operator throwing eslint errors. Had a chat on Discord regarding this and you suggested raising an issue. You mentioned that the eslint was not configured to handle the newer syntax.

I first ran into the issue in src > discover.exercise.js on the 03-data-fetching branch.

Screenshot

Screen Shot 2022-07-27 at 10 08 57 am

Solution/Instructions/API error in 04-authentication extra credit 1.

Hello! πŸ‘‹

Just spotted an error either in the solution of app.extra-1.js and in INSTRUCTIONS.MD or in the client function from src/utils/api-client.

The issue

Both app.extra-1.js and INSTRUCTIONS.MD suggest using the client function from src/utils/api-client kinda like this:

client('me', {token}) // token being just the bare string retrieved from localStorage

However, the function is expecting as an argument a customConfig object and spreads it right in the config object before passing it to fetch.

function client(endpoint, customConfig = {}) {
  const config = {
    method: 'GET',
    ...customConfig,
  }

  return window.fetch(`${apiURL}/${endpoint}`, config).then(async response => {
    const data = await response.json()
    if (response.ok) {
      return data
    } else {
      return Promise.reject(data)
    }
  })
}

Since we are passing {token} as the argument for the customConfig, it's getting spread and it's thus not getting set in the headers property of the config object that the Fetch API expects. This results in a 401 error and the app not being able to set the user back when you reload the page as the exercise suggests that should happen.

The solutions

Modifying the client's function signature

Any of these solutions wouldn't require further modifications in the INSTRUCTIONS.MD file nor the app.extra-1.js.

  1. Make it just spect a token object ??? πŸ‘Ž
function client(endpoint, {token}) {
  const config = {
    method: 'GET',
    headers: {
      Authorization: `Bearer ${token}`,
    },
  }
  // ...
}
  1. Make it spect a token object and a customConfig object. πŸ‘Ž
function client(endpoint, {token}, customConfig = {}) {
  const config = {
    method: 'GET',
    headers: {
      Authorization: `Bearer ${token}`,
    },
   ...customConfig,
  }
  // ...
}
  1. Something like this? (even if a bit counter-intuitive since it's not mapping to what people'd expect from the Fetch API) πŸ’―
function client(endpoint, {token, ...customConfig} = {}) {
  const config = {
    method: 'GET',
    headers: {
      Authorization: `Bearer ${token}`,
    },
   ...customConfig,
  }
  // ...
}

Modify INSTRUCTIONS.MD and app.extra-1.js

So both state that the way the client function should be used is like this: πŸ‘Ž

user = await client('me', {headers: {Authorization: `Bearer ${token}`}});

Do a mix of both. πŸ‘Œ

So both INSTRUCTIONS.MD and app.extra-1.js state that the way the client function should be used is like this:

user = await client('me', token);

And the function's signature could then be cleaner (well, at least more friendly):

function client(endpoint, token, customConfig = {}) {
  const config = {
    method: 'GET',
    headers: {
      Authorization: `Bearer ${token}`,
    },
   ...customConfig,
  }

  // ...
}

Probably there are several other solutions, these were just the most obvious ones. I'd be glad to submit a PR applying the one (:100: or :ok_hand:) you prefer!
Thank you!

Question: Why does discover page book list load multiple times?

Hello,

I added a console.log to print the books array in the discover page and when the app loads it calls the log 4 times in a row. I am wondering if this is by design or if there is some useEffect runaway.

other stuff...

function DiscoverBooksScreen() {
  const [query, setQuery] = React.useState('')
  const [hasSearched, setHasSearched] = React.useState()
  const {books, error, isLoading, isError, isSuccess} = useBookSearch(query)

  console.log(books)

  React.useEffect(() => {
    return () => refetchBookSearchQuery()
  }, [])

...other stuff

image

Question: useAsync method

Do you mind to explain what does the useAsync method does? like more an example or valid verbose description
Like literally I couldn't find any useful scenario to use this method.

Unable to iterate through the options after running `node go` ?

First of all I very much appreciate that you put together everything you've taught so far into this practical project to demonstrate real world scenarios.
However there's a weird bug when I tried node go:
image

But then hitting the "Up" arrow (or the "Down" arrow from the second time and on), the options are gone somehow:
image

So I have to memorize which option I was at to switch to another one.
Things were fine a few days ago and now this happened, so I thought I might have broke something on my fork then I tried to get a fresh clone of this repo to confirm, so it seems your recent update may have something to do with that. Please have a look, thank you.

Possible bug in Branch 06-cache-management

Hi Kent!

I could be jumping the gun here as I haven't completed the extra credits, just skimmed them, but it looks like when I'm mutating state, the components aren't updating. See gif for example:

v

Is this expected with first exercise?

ps. Also running through a situation where I'm seeing infinite requests taking place after a mutation, but I haven't been able to reproduce yet.

Possible Bug in exercises/03-data-fetching branch

Hi Kent!

I think I've set everything up correctly. I'm seeing a service worker related error on the 03-data-fetching branch (see image below), but not on master.

I wanted to bring it to your attention in case it's due to recent changes.

mock-service-worker

-Nash

Warning: unstable_flushDiscreteUpdates: Cannot flush updates when React is already rendering if debugger present

Hello @kentcdodds,
I was stepping through the code & if I put a debugger in the DiscoverBooksScreen then I get a "unstable_flushDiscreteUpdates..." warning.

Very curious why this happens, I had noticed exactly the same behavior in my app when I put a debugger in the component itself and searched frantically to see if I was doing something wrong but didn't see any literature on this. Any help/insight would be much appreciated.

Again, thank you so much for putting this course together, I'm really enjoying it.

Untitled

Untitled2

Error in Setup

Hello!

I'm setting up the bookshelf app and I'm having an issue. I have fully removed and cloned the app a few times with repeatable results. The setup seems to be failing the book-screen.js test. I'm wondering if this is something in my setup or are other people seeing this as well?

Thanks in advance!
-Mike

Here are the details

Commands run so far is:

git clone https://github.com/kentcdodds/bookshelf.git
cd bookshelf
npm run setup --silent

This command gives the following output:

▢️  Starting workshop setup...
      Running the following command: npx "https://gist.github.com/kentcdodds/bb452ffe53a5caa3600197e1d8005733" -q
npx: installed 1 in 1.391s
    ▢️  Starting: System Validation
          Ensuring the correct versions of tools are installed on this computer.
          Running the following command: npx "https://gist.github.com/kentcdodds/abbc32701f78fa70298d444c2303b6d9"
npx: installed 2 in 1.541s
    βœ…  Success: System Validation


    ▢️  Starting: Dependency Installation
          Installing third party code dependencies so the workshop works properly on this computer.
          Running the following command: npm install
husky > Setting up git hooks
husky > Done
added 2489 packages from 913 contributors and audited 2502 packages in 28.683s

117 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

    βœ…  Success: Dependency Installation


    ▢️  Starting: Project Validation
          Running validation checks to ensure dependencies were installed properly
          Running the following command: npm run validate -s

 RUNS  src/__tests__/book-screen.js
 PASS  src/utils/__tests__/use-async.jsjs
 PASS  src/utils/__tests__/misc.js
 PASS  src/utils/__tests__/api-client.js
 PASS  src/components/__tests__/modal.js
 PASS  src/components/__tests__/rating.js
 FAIL  src/__tests__/book-screen.js (5.005 s)
  ● console errors β€Ί note update failures are displayed

    TestingLibraryElementError: Unable to find an element with the role "alert"

    Here are the available roles:

      button:

      Name "Logout":
      <button
        class="css-105y6wg-Button-AuthenticatedApp e1baol0z3"
      />

      Name "Add to list":
      <button
        aria-label="Add to list"
        class="css-bnousp-CircleButton-TooltipButton e1baol0z0"
        data-reach-tooltip-trigger=""
      />

      --------------------------------------------------
      navigation:

      Name "":
      <nav
        class="css-17vy10h-Nav"
      />

      --------------------------------------------------
      list:

      Name "":
      <ul
        class="css-11z6h0h-Nav"
      />

      --------------------------------------------------
      listitem:

      Name "":
      <li />

      Name "":
      <li />

      Name "":
      <li />

      --------------------------------------------------
      link:

      Name "Reading List":
      <a
        class="css-14cbamv-NavLink"
        href="/list"
      />

      Name "Finished Books":
      <a
        class="css-14cbamv-NavLink"
        href="/finished"
      />

      Name "Discover":
      <a
        class="css-14cbamv-NavLink"
        href="/discover"
      />

      --------------------------------------------------
      main:

      Name "":
      <main
        class="css-12ehlsl-AuthenticatedApp"
      />

      --------------------------------------------------
      img:

      Name "dolorem sed doloremque book cover":
      <img
        alt="dolorem sed doloremque book cover"
        class="css-194shf0-BookScreen"
        src="http://placeimg.com/640/480"
      />

      --------------------------------------------------
      heading:

      Name "dolorem sed doloremque":
      <h1 />

      --------------------------------------------------

    <body>
      <div>
        <div
          class="css-1pz3cpr-AuthenticatedApp"
        >
          Tremayne.Mills62
          <button
            class="css-105y6wg-Button-AuthenticatedApp e1baol0z3"
          >
            Logout
          </button>
        </div>
        <div
          class="css-1dchfq2-AuthenticatedApp"
        >
          <div
            class="css-1bxv0zk-AuthenticatedApp"
          >
            <nav
              class="css-17vy10h-Nav"
            >
              <ul
                class="css-11z6h0h-Nav"
              >
                <li>
                  <a
                    class="css-14cbamv-NavLink"
                    href="/list"
                  >
                    Reading List
                  </a>
                </li>
                <li>
                  <a
                    class="css-14cbamv-NavLink"
                    href="/finished"
                  >
                    Finished Books
                  </a>
                </li>
                <li>
                  <a
                    class="css-14cbamv-NavLink"
                    href="/discover"
                  >
                    Discover
                  </a>
                </li>
              </ul>
            </nav>
          </div>
          <main
            class="css-12ehlsl-AuthenticatedApp"
          >
            <div>
              <div
                class="css-fkyky9-BookScreen"
              >
                <img
                  alt="dolorem sed doloremque book cover"
                  class="css-194shf0-BookScreen"
                  src="http://placeimg.com/640/480"
                />
                <div>
                  <div
                    class="css-1tpptxu-BookScreen"
                  >
                    <div
                      class="css-y9z24n-BookScreen"
                    >
                      <h1>
                        dolorem sed doloremque
                      </h1>
                      <div>
                        <i>
                          Ms. Winston Lebsack
                        </i>
                        <span
                          class="css-nn5rmi-BookScreen"
                        >
                          |
                        </span>
                        <i>
                          Mohr Inc
                        </i>
                      </div>
                    </div>
                    <div
                      class="css-1etzife-BookScreen"
                    >
                      <button
                        aria-label="Add to list"
                        class="css-bnousp-CircleButton-TooltipButton e1baol0z0"
                        data-reach-tooltip-trigger=""
                      >
                        <svg
                          fill="currentColor"
                          height="1em"
                          stroke="currentColor"
                          stroke-width="0"
                          viewBox="0 0 512 512"
                          width="1em"
                          xmlns="http://www.w3.org/2000/svg"
                        >
                          <path
                            d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm144 276c0 6.6-5.4 12-12 12h-92v92c0 6.6-5.4 12-12 12h-56c-6.6 0-12-5.4-12-12v-92h-92c-6.6 0-12-5.4-12-12v-56c0-6.6 5.4-12 12-12h92v-92c0-6.6 5.4-12 12-12h56c6.6 0 12 5.4 12 12v92h92c6.6 0 12 5.4 12 12v56z"
                          />
                        </svg>
                      </button>
                    </div>
                  </div>
                  <div
                    class="css-n6nwxy-BookScreen"
                  />
                  <br />
                  <p
                    class="css-mptbr-BookScreen"
                  >
                    Odit quisquam voluptatibus esse illum et numquam et nihil. Qui assumenda ut voluptas repellendus eos omnis. Delectus laudantium commodi autem vel voluptatem. Dignissimos est reiciendis provident maxime saepe deserunt ducimus aliquam et. Sit ducimus libero veritatis.
                  </p>
                </div>
              </div>
            </div>
          </main>
        </div>
      </div>
    </body>

      218 |     await waitForLoadingToFinish()
      219 | 
    > 220 |     expect(screen.getByRole('alert').textContent).toMatchInlineSnapshot(
          |                   ^
      221 |       `"There was an error: __test_error_message__"`,
      222 |     )
      223 |   })

      at Object.getElementError (node_modules/@testing-library/dom/dist/config.js:37:19)
      at node_modules/@testing-library/dom/dist/query-helpers.js:90:38
      at node_modules/@testing-library/dom/dist/query-helpers.js:62:17
      at getByRole (node_modules/@testing-library/dom/dist/query-helpers.js:106:19)
      at Object.<anonymous> (src/__tests__/book-screen.js:220:19)

-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |    69.5 |    52.67 |   65.41 |   69.62 |                   
 src               |   44.44 |    16.67 |   47.37 |   45.71 |                   
  app.js           |   83.33 |       50 |   66.67 |     100 | 14                
  auth-provider.js |   28.57 |        0 |   28.57 |   28.57 | 14-23,35-46       
  ...icated-app.js |     100 |       50 |     100 |     100 | 98                
  bootstrap.js     |       0 |        0 |       0 |       0 |                   
  index.js         |       0 |      100 |       0 |       0 | 9-10              
  ...icated-app.js |       0 |        0 |       0 |       0 | 12-64             
 src/components    |   66.67 |    47.92 |   69.44 |   65.12 |                   
  book-row.js      |       0 |        0 |       0 |       0 | 12-17             
  lib.js           |   94.44 |       50 |      75 |   94.44 | 144               
  ...-item-list.js |       0 |        0 |       0 |       0 | 10-32             
  logo.js          |       0 |        0 |       0 |       0 | 3-4               
  modal.js         |   94.12 |      100 |   90.91 |   92.86 | 35                
  profiler.js      |       0 |        0 |       0 |       0 | 4-43              
  rating.js        |   88.24 |       50 |   85.71 |    87.5 | 28-29             
  ...us-buttons.js |   85.71 |       75 |   85.71 |   85.71 | 28,72             
 src/context       |   72.34 |    56.25 |   64.29 |   76.19 |                   
  auth-context.js  |      75 |    66.67 |   58.33 |   78.38 | ...55-57,72,79,85 
  index.js         |   57.14 |       25 |     100 |      60 | 12-13             
 src/screens       |   41.38 |    40.48 |   33.33 |   40.74 |                   
  book.js          |     100 |    94.44 |     100 |     100 | 131               
  discover.js      |       0 |        0 |       0 |       0 | 14-94             
  finished.js      |       0 |      100 |       0 |       0 | 6-8               
  not-found.js     |       0 |      100 |       0 |       0 | 7                 
  reading-list.js  |       0 |      100 |       0 |       0 | 6-8               
 src/styles        |     100 |      100 |     100 |     100 |                   
  colors.js        |     100 |      100 |     100 |     100 |                   
  media-queries.js |     100 |      100 |     100 |     100 |                   
 src/utils         |      83 |     87.5 |   79.59 |   83.91 |                   
  api-client.js    |     100 |      100 |     100 |     100 |                   
  books.js         |   43.48 |       50 |   33.33 |   42.11 | 28-45,59-70       
  hooks.js         |     100 |      100 |     100 |     100 |                   
  list-items.js    |   88.57 |    77.78 |   90.91 |   89.29 | 17-19             
  misc.js          |     100 |      100 |     100 |     100 |                   
-------------------|---------|----------|---------|---------|-------------------
Test Suites: 1 failed, 5 passed, 6 total
Tests:       1 failed, 28 passed, 29 total
Snapshots:   3 passed, 3 total
Time:        7.959 s
Ran all test suites.
    🚨  Failure: Project Validation. Please review the messages above for information on how to troubleshoot and resolve this issue.

Running tests gives a type error.

What I'm running
node v12.16.1
npm v6.13.4
Mac OS

What I did?
I ran npm run test

What I expected
For the tests to run and stay in watch mode

What happened instead?

❯ npm t

> [email protected] test /Users/kevin/code/bookshelf
> react-scripts test --env=jest-environment-jsdom-sixteen

TypeError: fsevents is not a function
    at new FSEventsWatcher (/Users/kevin/code/bookshelf/node_modules/jest-haste-map/build/lib/FSEventsWatcher.js:162:20)
    at createWatcher (/Users/kevin/code/bookshelf/node_modules/jest-haste-map/build/index.js:1052:23)
    at Array.map (<anonymous>)
    at HasteMap._watch (/Users/kevin/code/bookshelf/node_modules/jest-haste-map/build/index.js:1230:44)
    at /Users/kevin/code/bookshelf/node_modules/jest-haste-map/build/index.js:517:21
    at Generator.next (<anonymous>)
    at asyncGeneratorStep (/Users/kevin/code/bookshelf/node_modules/jest-haste-map/build/index.js:193:24)
    at _next (/Users/kevin/code/bookshelf/node_modules/jest-haste-map/build/index.js:213:9)
npm ERR! Test failed.  See above for more details.

What I've tried
Tried googling around to find relevant issues.

Large applications ?

Hi @kentcdodds , do you think this architecture could work for large applications ? any recommendation on how to organize hooks and components for large apps ?

You know in React is so hard to find a bullet proof recipe for big apps with ton of business logic, a recipe that scales and you don't loose control over the code.

Placeholder is displayed instead of actual video track sometimes

It is not specific for this workshop, it occurred in previous ones as well.
In some cases when video starts, a placeholder is displayed instead of actual video track, though I can hear the audio one.
image
Only page refresh helps.

It happens rarely, but when it does, I can see such errors in console:
image

Error with command: npm start

Failed to compile
./src/screens/discover.js
Module not found: Can't resolve 'components/book-row' in 'C:\Users\p-c\Downloads\Github\bookshelf\src\screens'

useCallbackStatus usage

Hey @kentcdodds πŸ‘‹ , first of all thank you for sharing this code, it really helped me discover a new way to structure my react apps.

One question that I have is why did you use the hook useCallbackStatusinstead of just using react-async with a deferFn in the login form like this ?

Thank you ❀️

On branch 05-routing `npm start` errs out

Starting the server on this branch results in Unexpected token 'export'. To get it to work, I had to remove src/setupProxy.js.

I think this might be an issue for folks trying to solve the first exercise in this branch.

err

error when trying to register

When trying to register, after I click the register button I get this screen (using the codesandbox version):

A cross-origin error was thrown. React doesn't have access to the actual error object in development. See https://fb.me/react-crossorigin-error for more information.

Here are the stack frames, if that helps:
invokeGuardedCallbackDev
https://o7xpx2q255.csb.app/node_modules/react-dom/cjs/react-dom.development.js:408:19
invokeGuardedCallback
https://o7xpx2q255.csb.app/node_modules/react-dom/cjs/react-dom.development.js:454:31
beginWork$$1
https://o7xpx2q255.csb.app/node_modules/react-dom/cjs/react-dom.development.js:23217:7
performUnitOfWork
https://o7xpx2q255.csb.app/node_modules/react-dom/cjs/react-dom.development.js:22208:12
workLoopSync
https://o7xpx2q255.csb.app/node_modules/react-dom/cjs/react-dom.development.js:22185:22
renderRoot
https://o7xpx2q255.csb.app/node_modules/react-dom/cjs/react-dom.development.js:21878:11
runRootCallback
https://o7xpx2q255.csb.app/node_modules/react-dom/cjs/react-dom.development.js:21554:20
flushSyncCallbackQueueImpl/<
https://o7xpx2q255.csb.app/node_modules/react-dom/cjs/react-dom.development.js:11353:24
unstable_runWithPriority
https://o7xpx2q255.csb.app/node_modules/scheduler/cjs/scheduler.development.js:643:12
runWithPriority$2
https://o7xpx2q255.csb.app/node_modules/react-dom/cjs/react-dom.development.js:11305:10
flushSyncCallbackQueueImpl
https://o7xpx2q255.csb.app/node_modules/react-dom/cjs/react-dom.development.js:11349:7
flushSyncCallbackQueue
https://o7xpx2q255.csb.app/node_modules/react-dom/cjs/react-dom.development.js:11338:3
batchedEventUpdates$1
https://o7xpx2q255.csb.app/node_modules/react-dom/cjs/react-dom.development.js:21662:7
batchedEventUpdates
https://o7xpx2q255.csb.app/node_modules/react-dom/cjs/react-dom.development.js:2348:12
dispatchEventForPluginEventSystem
https://o7xpx2q255.csb.app/node_modules/react-dom/cjs/react-dom.development.js:5996:5
dispatchEvent
https://o7xpx2q255.csb.app/node_modules/react-dom/cjs/react-dom.development.js:6025:5

HMR Not working in Build an Epic React App workshop

In exercise 1 noticed that HMR is not working. Using Chrome I can see HMR is waiting for updates but even a simple text change does not get picked up without refreshing the page. Also, this seems to only be an issue with this workshop. Other workshops and even a new CRA HMR seems to work fine

[HMR] Waiting for update signal from WDS...

help explain the useAsync

I'm trying to break useAsync down, so I know why it's added and if it makes sense to adopt for my own projects.

This post has helped a good bit, but I'm not sure I see the whole picture yet:

questions

When should useAsync be used?
Is useAsync to help replace useQuery?

Here, run(onSubmit()) seems to be calling setData twice, right?

About useAsync Hooks

Thank you for providing such good learning materials. I have a question for you, I hope you can answer for me

function useSafeDispatch(dispatch) {
  const mounted = React.useRef(false)
  React.useLayoutEffect(() => {
    mounted.current = true
    return () => (mounted.current = false)
  }, [])
  return React.useCallback(
    (...args) => (mounted.current ? dispatch(...args) : void 0),
    [dispatch],
  )
}

Why do we need useSafeDispatch patch?
I know useLayoutEffect run after React has committed updates to the DOM,before the browser has a chance to paint.

** We are trying to prevent async task run before react commit update to the DOM?**

Exercise List bugged with git for windows

Running git 2.28.0.windows.1. Tested with cmd, powershell and git bash.

Somehow the --format option does not remove the ' character.

grafik

Original code:

const branches = spawnSync(
    `git for-each-ref --format='%(refname:short)'`,
  ).split('\n')

If this also works on linux/mac, a good fix would be to replace ' with ":

const branches = spawnSync(
    `git for-each-ref --format="%(refname:short)"`,
  ).split('\n')

If that does not work an alternative would be to remove ' if present:

const branches = spawnSync(`git for-each-ref --format='%(refname:short)'`)
    .split('\n')
    .map(b => b.replace(/(^')|('$)/g, ''))

Several videos with the same name cause unpredictable behavior

In Cache management exercise there are 2 Break Time videos. It seems, that they have the same ids or something and behave incorrectly:

  • you can be redirected to the second one after Solution 8 video;
  • uncompleted video is marked as Completed;
  • they are both highlighted in the playlist and so on.

image
image

Change error.code to error.status and ignore passwordHash in the return user object

  • I think it should change to error.status since you're using error.status everywhere (validateUser, authenticate, create, ...)

    error.code = 400

  • property passwordHash is in the return user object and I think this is not what you want. I saw you eliminate it in the read function

    return {...user, token: btoa(user.id)}

Uncaught exception in Promise

Hi Kent. Thanks for you helpful blog post and demo. Just wondering about resolving uncaught exceptions. For example in your demo click on the Login then Login without entering details: Uncaught (in promise) {status: 500, message: "Invalid username or password"}

If I catch an exception on e.g. login then I can't seem to get it to return/display the message. Is this perhaps to do with react-async processing?

Edit: Actually, a bit more checking and it looks like you just need to change Promise.reject to Promise.resolve in use-callback-status.js

Css selectors in the rating component

In the Rating component there is a rule that uses the important exception

[`.${rootClassName} &:hover ~ label`]: {
  color: `${colors.gray20} !important`,
},

I think I found better rules whitout such exception. Sorry, those are writen in styled-components library rather than in emotion:

const Container = styled.div`
  display: flex;
  > * {
    padding: 0 2px;
    :last-child {
      padding-right: 0;
    }
    :first-child {
      padding-left: 0;
    }
  }
  ${({ rating }) =>
    css`
      color: ${rating === -1 ? grey : orange};
    `}

  > label:hover ~ label > svg {
    color: ${grey};
  }
  input:checked ~ label {
    color: ${grey}
  }
  input:checked + label {
    color: ${orange}
  }
  :hover > label > svg {
    color: ${orange};
  }
`;

The container component above is the stars container div.

Instructions file missing.

Hello,

First of all thanks for uploading this repository which has been very helpful to me. I've been looking at it closely and I noticed the instructions are missing for the branch exercises/app-state. I'm not sure if this was intentional so I just wanted to let you know.

Thanks again.

Wait for the reload action to resolve?

Hi Kent!

Thanks for an excellent repo and demo. I've learned a lot studying this. I have a question/issue regarding the login function. The login function will resolve before the getUser, or in your case the bootstrapAppData function, request is completed and resolved, causing a little lag where we cant show a loading spinner in the component awaiting the login function. Do you have any idea how to solve this since the reload action doesn't return a promise?

const login = (credentials: any) => authClient.login(credentials).then(reload);

LoginForm.js

onSubmit={async ({ email, password }, actions) => {
    await login({ email, password });
    actions.setSubmitting(false); // will set to false before the reload action is finished
}}

suggest little change about useAsync hook

I copy & paste useAsync hook in my side project that has TS setup. In the process of add TS types, I find two places where code could have little changes to better migrate to TS.
all of them is inside of useSafeDispatch function.

React.useLayoutEffect(() => {
  mounted.current = true;
  return () => (mounted.current = false) // A
}, []);

Refer React d.ts file here

// NOTE: callbacks are _only_ allowed to return either void, or a destructor.
// The destructor is itself only allowed to return void.
type EffectCallback = () => (void | (() => void | undefined));

I think maybe we could change line A to:
return () => {mounted.current = false}
in order to match useLayoutEffect API requirement and remove TS error

and also change

return React.useCallback(
    (...args) => (mounted.current ? dispatch(...args) : void 0),
    [dispatch]
  );

to

return React.useCallback(
    (action) => (mounted.current ? dispatch(action) : void 0),
    [dispatch]
  );

due to dispatch TS type only accept one argument

// this technically does accept a second argument, but it's already under a deprecation warning
    // and it's not even released so probably better to not define it.
    type Dispatch<A> = (value: A) => void;

I'm just suggest those two changes here. maybe helpful for someone also encounter the same TS error

How to fix this?

index.js:559 [MSW] Detected outdated Service Worker: Currently active Service Worker (d1e0e502f550d40a34bee90822e4bf98) is behind the latest published one (65d33ca82955e1c5928aed19d1bdf3f9).

The mocking is still enabled, but it's highly recommended that you update your Service Worker by running:

$ npx msw init <PUBLIC_DIR>

This is necessary to ensure that the Service Worker is in sync with the library to guarantee its stability.
If this message still persists after updating, please report an issue: https://github.com/open-draft/msw/issues

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.