├── .gitignore
├── .vscode
└── settings.json
├── LICENSE
├── README.md
├── book-code-listings
├── chapter00
│ └── index.html
├── chapter01
│ ├── HelloWorld.js
│ ├── Listing0101.html
│ ├── Listing0102.js
│ ├── Listing0103.js
│ └── index.js
├── chapter03
│ ├── ConditionalWelcome.js
│ ├── ConditionalWelcome2.js
│ ├── ConditionalWelcome3.js
│ ├── CountUp.js
│ ├── FragmentExample1.js
│ ├── FragmentExample2.js
│ ├── Header.js
│ ├── ImmediateInvoke.js
│ ├── Login.js
│ ├── MyFancyComponent
│ │ ├── MyFancyComponent.js
│ │ └── MyFancyWidget.js
│ ├── SearchBox
│ │ ├── SearchBox.js
│ │ ├── SearchInput.js
│ │ └── SearchResults.js
│ ├── Welcome.js
│ ├── custom-attributes.html
│ ├── index.js
│ └── requirejs-demo
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── tools
│ │ ├── build.js
│ │ └── r.js
│ │ └── www
│ │ ├── app.js
│ │ ├── app
│ │ ├── main.js
│ │ └── messages.js
│ │ ├── index.html
│ │ └── lib
│ │ ├── print.js
│ │ └── require.js
├── chapter04
│ ├── BasicFigure.js
│ ├── BasicFigureProps.js
│ ├── BoundFunction.js
│ ├── ClassComponentState.js
│ ├── Counter.js
│ ├── CounterController.js
│ ├── CreateReactClass.js
│ ├── CutePicture.js
│ ├── Farm.js
│ ├── Farm
│ │ ├── Farm.js
│ │ ├── Farms.js
│ │ ├── ImprovedFarm.js
│ │ └── ImprovedFarms.js
│ ├── FigureList.js
│ ├── FigureListProps.js
│ ├── Foo.js
│ ├── FooFunction.js
│ ├── Joke.js
│ ├── LeakyCounter.js
│ ├── LoginForm
│ │ ├── LoginForm.js
│ │ ├── LoginSubmit.js
│ │ ├── PasswordInput.js
│ │ └── UsernameInput.js
│ ├── NoLeakCounter.js
│ ├── NoLeakCounterController.js
│ ├── PureComponent.js
│ ├── ReactClassComponent.js
│ ├── ReactMemoExample.js
│ ├── SetStateAsync.js
│ ├── ShallowCompare.js
│ ├── ShoppingCart
│ │ ├── Cart.css.js
│ │ ├── Cart.js
│ │ ├── CartItems.css.js
│ │ ├── CartItems.js
│ │ ├── CheckoutButton.js
│ │ ├── DisplayTotal.js
│ │ ├── Item.js
│ │ └── SingleComponentCart.js
│ ├── ThingsThatAreFunny.js
│ ├── ThingsThatILike.js
│ ├── ToDoClass.js
│ ├── ToDoFunction.js
│ ├── ToDoFunctionSimple.js
│ ├── UnboundFunction.js
│ ├── WelcomeMessage.js
│ ├── WelcomeTitle.js
│ ├── clone-element
│ │ ├── App.js
│ │ ├── NavBar.js
│ │ ├── NavBarChildren.js
│ │ ├── NavBarCloneChildren.js
│ │ ├── NavBarPassingOnClick.js
│ │ ├── NavBarUsingOnClick.js
│ │ └── NavItem.js
│ └── index.js
├── chapter06
│ ├── BorderBox.js
│ ├── Contact.js
│ ├── CounterClass.js
│ ├── CounterClass2.js
│ ├── CounterClass3.js
│ ├── CounterClass4.js
│ ├── DisplayPrimaryColors.js
│ ├── Dog.js
│ ├── FamilyTree.js
│ ├── IncrementTwice.js
│ ├── IncrementTwiceFixed.js
│ ├── Map.js
│ ├── NewsFeed.js
│ ├── NewsFeed2.js
│ ├── NewsFeed3.js
│ ├── NewsFeed4.js
│ ├── Person.js
│ ├── PropsMutation
│ │ └── App.js
│ ├── Reminders
│ │ ├── App.js
│ │ ├── FilterSelect.js
│ │ ├── InputForm.js
│ │ ├── Reminder.js
│ │ ├── RemindersList.js
│ │ ├── index.css
│ │ ├── index.js
│ │ └── reportWebVitals.js
│ ├── RemindersClass
│ │ ├── App.js
│ │ ├── FilterSelect.js
│ │ ├── InputForm.js
│ │ ├── Reminder.js
│ │ ├── RemindersList.js
│ │ ├── index.css
│ │ ├── index.js
│ │ └── reportWebVitals.js
│ ├── SiteLink.js
│ ├── SiteLinkNode.js
│ ├── StoreList.js
│ ├── StoresNearYou.js
│ ├── StoresNearYou1.js
│ ├── StoresNearYou2.js
│ ├── StoresNearYou3.js
│ ├── StoresNearYou4.js
│ ├── StoresNearYou5.js
│ ├── StoresNearYou6.js
│ ├── StoresNearYou7.js
│ ├── StoresNearYou8.js
│ ├── WelcomeClass.js
│ ├── WelcomeMessage.js
│ └── index.js
├── chapter07
│ ├── CoffeeMachine.js
│ ├── ColorWheel.js
│ ├── ColorWheel2.js
│ ├── ColorWheel3.js
│ ├── ColorWheel4.js
│ ├── EventListener.js
│ ├── EventObject.js
│ ├── EventObject2.js
│ ├── EventProps.js
│ ├── ScreenDoor.js
│ ├── Search.js
│ ├── WarningButton.js
│ └── index.js
├── chapter08
│ ├── BlogComment.js
│ ├── Controlled1.js
│ ├── Controlled2.js
│ ├── Controlled3.js
│ ├── Controlled4.js
│ ├── SearchForm
│ │ ├── SearchBox.js
│ │ ├── SearchInput.js
│ │ └── SearchResults.js
│ ├── SignUpForm.js
│ ├── SizeSelect.js
│ ├── TermsOfUse.js
│ ├── Uncontrolled1.js
│ └── index.js
├── chapter09
│ ├── AudioPlayer.js
│ ├── CodeDisplay.js
│ ├── CreateRefClass.js
│ ├── CreateRefFunction.js
│ ├── ScrollToDemo.js
│ ├── TextReader.js
│ ├── TextReaderCallback.js
│ ├── TextReaderCallback2.js
│ ├── index.js
│ └── mobydick.js
├── chapter10
│ ├── ArticleLink.js
│ ├── CSSModule.js
│ ├── DisplayStatus.js
│ ├── ExampleStyled.js
│ ├── StyledChild.js
│ ├── StyledParent.js
│ ├── WarningMessage.js
│ ├── WarningMessageVars.js
│ ├── index.js
│ ├── messageStyles.js
│ ├── my-component.module.css
│ └── style.css
├── chapter11
│ ├── CallMe.js
│ ├── CallMeFixed.js
│ ├── CountingBox.js
│ ├── NumberGuessing.js
│ ├── PassingSetter.js
│ ├── ReducerCounter.js
│ ├── ReducerCounterPayload.js
│ ├── RenderCounter.js
│ ├── ShippingAddress.js
│ ├── ShippingAddress2.js
│ ├── TimerConditionalDemo.js
│ ├── TimerDemo.js
│ ├── TimerOnceDemo.js
│ ├── TimerRestartDemo.js
│ ├── UsingContext.js
│ ├── UsingUseForm.js
│ ├── WeatherWidget.js
│ ├── WordCount.js
│ ├── index.js
│ ├── theme-context.js
│ └── useZipLookup.js
├── chapter12-react-router-v6
│ ├── ChooseYourAdventure.js
│ ├── ComponentProp.js
│ ├── MultipleMatches.js
│ ├── NavMenu.js
│ ├── NavMenuExact.js
│ ├── NavMenuWithRouter.js
│ ├── NestedRoutes.js
│ ├── PathOptions.js
│ ├── RedirectRoute.js
│ ├── RenderProp.js
│ ├── URLParams.js
│ ├── URLParamsHook.js
│ ├── UsingHistory.js
│ ├── ViewLocation.js
│ └── ViewMatch.js
├── chapter12
│ ├── ChooseYourAdventure.js
│ ├── ComponentProp.js
│ ├── MultipleMatches.js
│ ├── NavMenu.js
│ ├── NavMenuExact.js
│ ├── NavMenuWithRouter.js
│ ├── NestedRoutes.js
│ ├── PathOptions.js
│ ├── RedirectRoute.js
│ ├── RenderProp.js
│ ├── URLParams.js
│ ├── URLParamsHook.js
│ ├── UsingHistory.js
│ ├── ViewLocation.js
│ ├── ViewMatch.js
│ └── index.js
├── chapter13
│ ├── BadComponent.js
│ ├── BadComponentWithBoundary.js
│ ├── ErrorBoundary.js
│ ├── ErrorBoundaryLib.js
│ ├── ErrorBoundaryWithDidCatch.js
│ ├── ErrorBoundaryWithLogging.js
│ ├── ErrorBoundaryWithReset.js
│ ├── ErrorFallback.js
│ ├── Fallback.js
│ ├── SampleTree.js
│ ├── SampleTreeWithBoundary.js
│ ├── SometimesBad.js
│ ├── UseErrorHandler.js
│ ├── index.js
│ └── logger.js
├── chapter15
│ └── custom-toolchain
│ │ ├── babel.config.json
│ │ ├── package-lock.json
│ │ ├── package.json
│ │ ├── src
│ │ ├── App.js
│ │ ├── App.test.js
│ │ ├── index.html
│ │ └── index.js
│ │ └── webpack.config.js
├── chapter16
│ ├── Clicker1.js
│ ├── Clicker2.js
│ ├── Clicker3.js
│ ├── Clicker4.js
│ ├── Restful.js
│ ├── Restful2.js
│ ├── index.js
│ └── style.css
├── chapter17
│ ├── App.js
│ ├── ComponentOutsideContext.js
│ ├── DashboardApp.js
│ ├── DashboardAppComposition.js
│ ├── DashboardAppContext.js
│ ├── Header.js
│ ├── PropDrilling.js
│ ├── UserPrefs.js
│ ├── contexts
│ │ └── UnitsContext.js
│ └── index.js
├── chapter18
│ └── portaldemo
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── package-lock.json
│ │ ├── package.json
│ │ ├── public
│ │ ├── favicon.ico
│ │ ├── images
│ │ │ └── chart.png
│ │ ├── index.html
│ │ ├── logo192.png
│ │ ├── logo512.png
│ │ ├── manifest.json
│ │ └── robots.txt
│ │ └── src
│ │ ├── App.css
│ │ ├── App.js
│ │ ├── App.test.js
│ │ ├── Chart.js
│ │ ├── Modal.js
│ │ ├── ModalWithoutPortal.js
│ │ ├── SalesChart.js
│ │ ├── SideBarHelp.js
│ │ ├── index.css
│ │ ├── index.js
│ │ ├── logo.svg
│ │ ├── reportWebVitals.js
│ │ ├── setupTests.js
│ │ └── styles.css
├── chapter19
│ └── index.js
└── package-lock.json
├── custom-toolchain
├── .eslintrc.js
├── babel.config.json
├── package-lock.json
├── package.json
├── src
│ ├── App.js
│ ├── App.test.js
│ ├── index.html
│ └── index.js
└── webpack.config.js
├── navigation-demo
├── .gitignore
├── README.md
├── package-lock.json
├── package.json
├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── robots.txt
└── src
│ ├── App.css
│ ├── App.js
│ ├── App.test.js
│ ├── index.css
│ ├── index.js
│ ├── logo.svg
│ ├── reportWebVitals.js
│ └── setupTests.js
├── next-reactjsfoundations.com
└── nextjs-blog
│ ├── .gitignore
│ ├── README.md
│ ├── package-lock.json
│ ├── package.json
│ ├── pages
│ ├── index.js
│ └── posts
│ │ └── first-post.js
│ └── public
│ ├── favicon.ico
│ └── vercel.svg
├── package-lock.json
├── react-book-store
├── README.md
├── build
│ ├── asset-manifest.json
│ ├── data
│ │ └── products.json
│ ├── favicon.ico
│ ├── images
│ │ ├── default.jpg
│ │ ├── fairy-tales.jpg
│ │ ├── le-pere-goriot.jpg
│ │ ├── molloy-malone-dies-the-unnamable.jpg
│ │ ├── njals-saga.jpg
│ │ ├── one-thousand-and-one-nights.jpg
│ │ ├── pride-and-prejudice.jpg
│ │ ├── the-book-of-job.jpg
│ │ ├── the-decameron.jpg
│ │ ├── the-divine-comedy.jpg
│ │ ├── the-epic-of-gilgamesh.jpg
│ │ └── things-fall-apart.jpg
│ ├── index.html
│ ├── manifest.json
│ └── static
│ │ ├── css
│ │ ├── 2.43b2b750.chunk.css
│ │ ├── 2.43b2b750.chunk.css.map
│ │ ├── main.3f9ef032.chunk.css
│ │ └── main.3f9ef032.chunk.css.map
│ │ └── js
│ │ ├── 2.3572893f.chunk.js
│ │ ├── 2.3572893f.chunk.js.LICENSE.txt
│ │ ├── 2.3572893f.chunk.js.map
│ │ ├── main.ee531687.chunk.js
│ │ ├── main.ee531687.chunk.js.map
│ │ ├── runtime-main.c9348604.js
│ │ └── runtime-main.c9348604.js.map
├── package-lock.json
├── package.json
├── public
│ ├── data
│ │ └── products.json
│ ├── favicon.ico
│ ├── images
│ │ ├── default.jpg
│ │ ├── fairy-tales.jpg
│ │ ├── le-pere-goriot.jpg
│ │ ├── molloy-malone-dies-the-unnamable.jpg
│ │ ├── njals-saga.jpg
│ │ ├── one-thousand-and-one-nights.jpg
│ │ ├── pride-and-prejudice.jpg
│ │ ├── the-book-of-job.jpg
│ │ ├── the-decameron.jpg
│ │ ├── the-divine-comedy.jpg
│ │ ├── the-epic-of-gilgamesh.jpg
│ │ └── things-fall-apart.jpg
│ ├── index.html
│ └── manifest.json
└── src
│ ├── App.css
│ ├── App.js
│ ├── App.test.js
│ ├── components
│ ├── Cart.css.js
│ ├── Cart.js
│ ├── Cart.test.js
│ ├── CartItem.css.js
│ ├── CartItem.js
│ ├── CartItem.test.js
│ ├── Product.css.js
│ ├── Product.js
│ ├── Product.test.js
│ ├── ProductList.css.js
│ ├── ProductList.js
│ └── ProductList.test.js
│ ├── data
│ └── products.js
│ ├── index.css
│ ├── index.js
│ ├── logo.svg
│ ├── registerServiceWorker.js
│ └── setUpTests.js
└── reactjsfoundations.com
├── .gitignore
├── README.md
├── config.overrides.js
├── package-lock.json
├── package.json
├── public
├── Listing01-01
│ ├── HelloWorld.js
│ └── index.html
├── _redirects
├── android-chrome-192x192.png
├── android-chrome-512x512.png
├── apple-touch-icon.png
├── favicon-16x16.png
├── favicon-32x32.png
├── favicon.ico
├── images
│ ├── cat.png
│ ├── chickens.png
│ ├── chris-and-car.jpeg
│ ├── cover.jpg
│ ├── cover.webp
│ └── dog.png
├── index.html
├── manifest.json
├── robots.txt
└── sitemap.xml
├── sitemap-gen.js
├── src
├── About.js
├── App.css
├── App.js
├── BottomNav.js
├── CodeLinks.js
├── ErrorFallback.js
├── HomePage.js
├── Introduction.js
├── MainNav.js
├── PrevNext.js
├── ScrollToTop.js
├── WhereToBuy.js
├── WpBlog.js
├── WpBlogSP.js
├── WpBlogWidget.js
├── chapter00
│ └── index.html
├── chapter01
│ ├── HelloWorld.js
│ ├── Listing0101.html
│ ├── Listing0102.js
│ ├── Listing0103.js
│ └── index.js
├── chapter03
│ ├── ConditionalWelcome.js
│ ├── ConditionalWelcome2.js
│ ├── ConditionalWelcome3.js
│ ├── CountUp.js
│ ├── FragmentExample1.js
│ ├── FragmentExample2.js
│ ├── Header.js
│ ├── ImmediateInvoke.js
│ ├── Login.js
│ ├── MyFancyComponent
│ │ ├── MyFancyComponent.js
│ │ └── MyFancyWidget.js
│ ├── SearchBox
│ │ ├── SearchBox.js
│ │ ├── SearchInput.js
│ │ └── SearchResults.js
│ ├── Welcome.js
│ ├── custom-attributes.html
│ ├── index.js
│ └── requirejs-demo
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── tools
│ │ ├── build.js
│ │ └── r.js
│ │ └── www
│ │ ├── app.js
│ │ ├── app
│ │ ├── main.js
│ │ └── messages.js
│ │ ├── index.html
│ │ └── lib
│ │ ├── print.js
│ │ └── require.js
├── chapter04
│ ├── BasicFigure.js
│ ├── BasicFigureProps.js
│ ├── BoundFunction.js
│ ├── ClassComponentState.js
│ ├── Counter.js
│ ├── CounterController.js
│ ├── CreateReactClass.js
│ ├── CutePicture.js
│ ├── Farm.js
│ ├── Farm
│ │ ├── Farm.js
│ │ ├── Farms.js
│ │ ├── ImprovedFarm.js
│ │ └── ImprovedFarms.js
│ ├── FigureList.js
│ ├── FigureListProps.js
│ ├── Foo.js
│ ├── FooFunction.js
│ ├── Joke.js
│ ├── LeakyCounter.js
│ ├── LoginForm
│ │ ├── LoginForm.js
│ │ ├── LoginSubmit.js
│ │ ├── PasswordInput.js
│ │ └── UsernameInput.js
│ ├── NoLeakCounter.js
│ ├── NoLeakCounterController.js
│ ├── PureComponent.js
│ ├── ReactClassComponent.js
│ ├── ReactMemoExample.js
│ ├── SetStateAsync.js
│ ├── ShallowCompare.js
│ ├── ShoppingCart
│ │ ├── Cart.css.js
│ │ ├── Cart.js
│ │ ├── CartItems.css.js
│ │ ├── CartItems.js
│ │ ├── CheckoutButton.js
│ │ ├── DisplayTotal.js
│ │ ├── Item.js
│ │ └── SingleComponentCart.js
│ ├── ThingsThatAreFunny.js
│ ├── ThingsThatILike.js
│ ├── ToDoClass.js
│ ├── ToDoFunction.js
│ ├── ToDoFunctionSimple.js
│ ├── UnboundFunction.js
│ ├── WelcomeMessage.js
│ ├── WelcomeTitle.js
│ ├── clone-element
│ │ ├── App.js
│ │ ├── NavBar.js
│ │ ├── NavBarChildren.js
│ │ ├── NavBarCloneChildren.js
│ │ ├── NavBarPassingOnClick.js
│ │ ├── NavBarUsingOnClick.js
│ │ └── NavItem.js
│ └── index.js
├── chapter06
│ ├── BorderBox.js
│ ├── Contact.js
│ ├── CounterClass.js
│ ├── CounterClass2.js
│ ├── CounterClass3.js
│ ├── CounterClass4.js
│ ├── DisplayPrimaryColors.js
│ ├── Dog.js
│ ├── FamilyTree.js
│ ├── IncrementTwice.js
│ ├── IncrementTwiceFixed.js
│ ├── Map.js
│ ├── NewsFeed.js
│ ├── NewsFeed2.js
│ ├── NewsFeed3.js
│ ├── NewsFeed4.js
│ ├── Person.js
│ ├── PropsMutation
│ │ └── App.js
│ ├── Reminders
│ │ └── reminders-app
│ │ │ ├── README.md
│ │ │ ├── package-lock.json
│ │ │ ├── package.json
│ │ │ ├── public
│ │ │ ├── favicon.ico
│ │ │ ├── index.html
│ │ │ ├── logo192.png
│ │ │ ├── logo512.png
│ │ │ ├── manifest.json
│ │ │ └── robots.txt
│ │ │ └── src
│ │ │ ├── App.css
│ │ │ ├── App.js
│ │ │ ├── FilterSelect.js
│ │ │ ├── InputForm.js
│ │ │ ├── Reminder.js
│ │ │ ├── RemindersList.js
│ │ │ ├── index.css
│ │ │ ├── index.js
│ │ │ ├── logo.svg
│ │ │ ├── reportWebVitals.js
│ │ │ └── setupTests.js
│ ├── RemindersClass
│ │ ├── App.js
│ │ ├── FilterSelect.js
│ │ ├── InputForm.js
│ │ ├── Reminder.js
│ │ ├── RemindersList.js
│ │ ├── index.css
│ │ ├── index.js
│ │ └── reportWebVitals.js
│ ├── SiteLink.js
│ ├── SiteLinkNode.js
│ ├── StoreList.js
│ ├── StoresNearYou.js
│ ├── StoresNearYou1.js
│ ├── StoresNearYou2.js
│ ├── StoresNearYou3.js
│ ├── StoresNearYou4.js
│ ├── StoresNearYou5.js
│ ├── StoresNearYou6.js
│ ├── StoresNearYou7.js
│ ├── StoresNearYou8.js
│ ├── WelcomeClass.js
│ ├── WelcomeMessage.js
│ └── index.js
├── chapter07
│ ├── CoffeeMachine.js
│ ├── ColorWheel.js
│ ├── ColorWheel2.js
│ ├── ColorWheel3.js
│ ├── ColorWheel4.js
│ ├── EventListener.js
│ ├── EventObject.js
│ ├── EventObject2.js
│ ├── EventProps.js
│ ├── ScreenDoor.js
│ ├── Search.js
│ ├── WarningButton.js
│ └── index.js
├── chapter08
│ ├── BlogComment.js
│ ├── Controlled1.js
│ ├── Controlled2.js
│ ├── Controlled3.js
│ ├── Controlled4.js
│ ├── SearchForm
│ │ ├── SearchBox.js
│ │ ├── SearchInput.js
│ │ └── SearchResults.js
│ ├── SignUpForm.js
│ ├── SizeSelect.js
│ ├── TermsOfUse.js
│ ├── Uncontrolled1.js
│ └── index.js
├── chapter09
│ ├── AudioPlayer.js
│ ├── CodeDisplay.js
│ ├── CreateRefClass.js
│ ├── CreateRefFunction.js
│ ├── ScrollToDemo.js
│ ├── TextReader.js
│ ├── TextReaderCallback.js
│ ├── TextReaderCallback2.js
│ ├── index.js
│ └── mobydick.js
├── chapter10
│ ├── ArticleLink.js
│ ├── CSSModule.js
│ ├── DisplayStatus.js
│ ├── ExampleStyled.js
│ ├── StyledChild.js
│ ├── StyledParent.js
│ ├── WarningMessage.js
│ ├── WarningMessageVars.js
│ ├── index.js
│ ├── messageStyles.js
│ ├── my-component.module.css
│ └── style.css
├── chapter11
│ ├── CallMe.js
│ ├── CallMeFixed.js
│ ├── CountingBox.js
│ ├── NumberGuessing.js
│ ├── PassingSetter.js
│ ├── ReducerCounter.js
│ ├── ReducerCounterPayload.js
│ ├── RenderCounter.js
│ ├── ShippingAddress.js
│ ├── ShippingAddress2.js
│ ├── TimerConditionalDemo.js
│ ├── TimerDemo.js
│ ├── TimerOnceDemo.js
│ ├── TimerRestartDemo.js
│ ├── UsingContext.js
│ ├── UsingUseForm.js
│ ├── WeatherWidget.js
│ ├── WordCount.js
│ ├── index.js
│ ├── theme-context.js
│ └── useZipLookup.js
├── chapter12
│ ├── ChooseYourAdventure.js
│ ├── ComponentProp.js
│ ├── MultipleMatches.js
│ ├── NavMenu.js
│ ├── NavMenuExact.js
│ ├── NavMenuWithRouter.js
│ ├── NestedRoutes.js
│ ├── PathOptions.js
│ ├── RedirectRoute.js
│ ├── RenderProp.js
│ ├── URLParams.js
│ ├── URLParamsHook.js
│ ├── UsingHistory.js
│ ├── ViewLocation.js
│ ├── ViewMatch.js
│ └── index.js
├── chapter13
│ ├── BadComponent.js
│ ├── BadComponentWithBoundary.js
│ ├── ErrorBoundary.js
│ ├── ErrorBoundaryLib.js
│ ├── ErrorBoundaryWithDidCatch.js
│ ├── ErrorBoundaryWithLogging.js
│ ├── ErrorBoundaryWithReset.js
│ ├── ErrorFallback.js
│ ├── Fallback.js
│ ├── SampleTree.js
│ ├── SampleTreeWithBoundary.js
│ ├── SometimesBad.js
│ ├── UseErrorHandler.js
│ ├── index.js
│ └── logger.js
├── chapter15
│ └── custom-toolchain
│ │ ├── babel.config.json
│ │ ├── package-lock.json
│ │ ├── package.json
│ │ ├── src
│ │ ├── App.js
│ │ ├── App.test.js
│ │ ├── index.html
│ │ └── index.js
│ │ └── webpack.config.js
├── chapter16
│ ├── Clicker1.js
│ ├── Clicker2.js
│ ├── Clicker3.js
│ ├── Clicker4.js
│ ├── Restful.js
│ ├── Restful2.js
│ ├── index.js
│ └── style.css
├── chapter17
│ ├── App.js
│ ├── ComponentOutsideContext.js
│ ├── DashboardApp.js
│ ├── DashboardAppComposition.js
│ ├── DashboardAppContext.js
│ ├── Header.js
│ ├── PropDrilling.js
│ ├── UserPrefs.js
│ ├── contexts
│ │ └── UnitsContext.js
│ └── index.js
├── chapter18
│ ├── index.html
│ ├── index.js
│ └── portaldemo
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── package-lock.json
│ │ ├── package.json
│ │ ├── public
│ │ ├── favicon.ico
│ │ ├── images
│ │ │ └── chart.png
│ │ ├── index.html
│ │ ├── logo192.png
│ │ ├── logo512.png
│ │ ├── manifest.json
│ │ └── robots.txt
│ │ └── src
│ │ ├── App.css
│ │ ├── App.js
│ │ ├── App.test.js
│ │ ├── Chart.js
│ │ ├── Modal.js
│ │ ├── ModalWithoutPortal.js
│ │ ├── SalesChart.js
│ │ ├── SideBarHelp.js
│ │ ├── index.css
│ │ ├── index.js
│ │ ├── logo.svg
│ │ ├── reportWebVitals.js
│ │ ├── setupTests.js
│ │ └── styles.css
├── chapter19
│ └── index.js
├── index.js
├── routes.js
├── setupTests.js
├── sitemap-routes.js
└── usePageTracking.js
└── yarn.lock
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "liveServer.settings.port": 5501
3 | }
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-js-foundations
2 |
3 | This repo contains all the code examples from React JS Foundations: Building User Interfaces with React JS by Chris Minnick (ISBN 978-1-119-68554-8).
4 |
5 | The code listings from the book are in book-code-listings.
6 |
7 | If you find an error in the code, please let me know.
8 |
--------------------------------------------------------------------------------
/book-code-listings/chapter00/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/book-code-listings/chapter01/HelloWorld.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | class HelloWorld extends React.Component {
4 | constructor(props) {
5 | super(props);
6 | this.state = { personName: "World" };
7 | }
8 |
9 | render() {
10 | return React.createElement("h1", null, "Hello, " + this.state.personName);
11 | }
12 | }
13 |
14 | const domContainer = document.querySelector("#app");
15 | ReactDOM.render(React.createElement(HelloWorld), domContainer);
16 |
--------------------------------------------------------------------------------
/book-code-listings/chapter01/Listing0101.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Hello, World!
7 |
8 |
9 |
10 |
14 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/book-code-listings/chapter01/Listing0102.js:
--------------------------------------------------------------------------------
1 | function Listing0102() {
2 | return (
3 |
4 | );
5 | }
6 |
7 | export default Listing0102;
8 |
--------------------------------------------------------------------------------
/book-code-listings/chapter01/Listing0103.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | function App() {
4 | const [personName, setPersonName] = React.useState("");
5 |
6 | return (
7 |
8 |
9 |
Hello {personName}
10 | setPersonName(e.target.value)} />
11 |
12 |
13 |
14 |
15 | );
16 | }
17 |
18 | export default App;
19 |
--------------------------------------------------------------------------------
/book-code-listings/chapter01/index.js:
--------------------------------------------------------------------------------
1 | export { default as Listing0102 } from "./Listing0102";
2 | export { default as Listing0103 } from "./Listing0103";
3 |
--------------------------------------------------------------------------------
/book-code-listings/chapter03/ConditionalWelcome.js:
--------------------------------------------------------------------------------
1 | import Header from "./Header";
2 | import Login from "./Login";
3 |
4 | function Welcome({ loggedIn }) {
5 | let header;
6 |
7 | if (loggedIn) {
8 | header = ;
9 | } else {
10 | header = ;
11 | }
12 | return (
13 | <>
14 | {header}
15 |
16 | >
17 | );
18 | }
19 |
20 | export default Welcome;
--------------------------------------------------------------------------------
/book-code-listings/chapter03/ConditionalWelcome2.js:
--------------------------------------------------------------------------------
1 | import Header from "./Header";
2 |
3 | function Welcome({ loggedIn }) {
4 | return (
5 | <>
6 |
7 | {loggedIn && }
8 | Note: if you don't see the welcome messsage, you're not logged in.
9 |
10 |
11 | >
12 | );
13 | }
14 |
15 | export default Welcome;
16 |
--------------------------------------------------------------------------------
/book-code-listings/chapter03/ConditionalWelcome3.js:
--------------------------------------------------------------------------------
1 | import Header from "./Header";
2 | import Login from "./Login";
3 |
4 | function Welcome({ loggedIn }) {
5 | return (
6 | <>
7 | {loggedIn ? : }
8 |
9 | >
10 | );
11 | }
12 |
13 | export default Welcome;
14 |
--------------------------------------------------------------------------------
/book-code-listings/chapter03/CountUp.js:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 |
3 | function CountUp() {
4 | const [count, setCount] = useState(0);
5 | return (
6 | <>
7 |
8 |
9 | {count}
10 |
11 |
12 | >
13 | );
14 | }
15 |
16 | export default CountUp;
17 |
--------------------------------------------------------------------------------
/book-code-listings/chapter03/FragmentExample1.js:
--------------------------------------------------------------------------------
1 | import { Fragment } from "react";
2 |
3 | function MyComponent() {
4 | return (
5 |
6 | The heading
7 | The subheading
8 |
9 |
10 | );
11 | }
12 |
13 | export default MyComponent;
14 |
--------------------------------------------------------------------------------
/book-code-listings/chapter03/FragmentExample2.js:
--------------------------------------------------------------------------------
1 | function MyComponent() {
2 | return (
3 | <>
4 | The heading
5 | The subheading
6 |
7 | >
8 | );
9 | }
10 |
11 | export default MyComponent;
12 |
--------------------------------------------------------------------------------
/book-code-listings/chapter03/Header.js:
--------------------------------------------------------------------------------
1 | function Header(props) {
2 | return (
3 | <>
4 | Welcome to My Website
5 |
6 | >
7 | );
8 | }
9 | export default Header;
10 |
--------------------------------------------------------------------------------
/book-code-listings/chapter03/ImmediateInvoke.js:
--------------------------------------------------------------------------------
1 | function ImmediateInvoke() {
2 | return (
3 | <>
4 |
5 | {(() => (
6 |
The Header
7 | ))()}
8 |
9 |
10 | >
11 | );
12 | }
13 | export default ImmediateInvoke;
14 |
--------------------------------------------------------------------------------
/book-code-listings/chapter03/Login.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | function Login() {
4 | const handleSubmit = (e) => {
5 | e.preventDefault();
6 | console.log(`logging in ${e.target[0].value}`);
7 |
8 | // do something else here
9 | };
10 |
11 | return (
12 | <>
13 |
18 |
19 |
20 | >
21 | );
22 | }
23 |
24 | export default Login;
25 |
--------------------------------------------------------------------------------
/book-code-listings/chapter03/MyFancyComponent/MyFancyComponent.js:
--------------------------------------------------------------------------------
1 | import MyFancyWidget from "./MyFancyWidget";
2 |
3 | function MyFancyComponent(props) {
4 | return (
5 | <>
6 |
11 |
12 | >
13 | );
14 | }
15 | export default MyFancyComponent;
16 |
--------------------------------------------------------------------------------
/book-code-listings/chapter03/MyFancyComponent/MyFancyWidget.js:
--------------------------------------------------------------------------------
1 | function MyFancyWidget(props) {
2 | return (
3 |
4 | - Widget Size: {props.widgetSize}
5 | - Number Of Columns: {props.numberOfColumns}
6 | - Title: {props.title}
7 |
8 | );
9 | }
10 | export default MyFancyWidget;
11 |
--------------------------------------------------------------------------------
/book-code-listings/chapter03/SearchBox/SearchBox.js:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 | import SearchInput from "./SearchInput";
3 | import SearchResults from "./SearchResults";
4 |
5 | function SearchBox() {
6 | const [searchTerm, setSearchTerm] = useState("");
7 |
8 | return (
9 | <>
10 |
11 |
12 |
13 |
14 |
15 | >
16 | );
17 | }
18 |
19 | export default SearchBox;
20 |
--------------------------------------------------------------------------------
/book-code-listings/chapter03/SearchBox/SearchInput.js:
--------------------------------------------------------------------------------
1 | function SearchInput(props) {
2 | return (
3 |
4 | {
9 | props.onChange(e.target.value);
10 | }}
11 | />
12 |
13 | );
14 | }
15 | export default SearchInput;
16 |
--------------------------------------------------------------------------------
/book-code-listings/chapter03/SearchBox/SearchResults.js:
--------------------------------------------------------------------------------
1 | function SearchResults(props) {
2 | return Searching for: {props.term}
;
3 | }
4 | export default SearchResults;
5 |
--------------------------------------------------------------------------------
/book-code-listings/chapter03/Welcome.js:
--------------------------------------------------------------------------------
1 | import Header from "./Header";
2 |
3 | function Welcome() {
4 | let header = ;
5 | return (
6 | <>
7 | {header}
8 |
9 | >
10 | );
11 | }
12 | export default Welcome;
13 |
--------------------------------------------------------------------------------
/book-code-listings/chapter03/custom-attributes.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Using data-attributes
7 |
8 |
9 |
10 | My Favorite T-Shirt
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/book-code-listings/chapter03/requirejs-demo/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "amd": {},
3 | "volo": {
4 | "baseUrl": "www/lib"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/book-code-listings/chapter03/requirejs-demo/tools/build.js:
--------------------------------------------------------------------------------
1 | {
2 | "appDir": "../www",
3 | "mainConfigFile": "../www/app.js",
4 | "dir": "../www-built",
5 | // List the modules that will be optimized.
6 | "modules": [
7 | {
8 | // module names are relative to baseUrl
9 | "name": "app"
10 | }
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/book-code-listings/chapter03/requirejs-demo/www/app.js:
--------------------------------------------------------------------------------
1 | // For any third party dependencies, like jQuery, place them in the lib folder.
2 |
3 | // Configure loading modules from the lib directory,
4 | // except for 'app' ones, which are in a sibling
5 | // directory.
6 | requirejs.config({
7 | baseUrl: "lib",
8 | paths: {
9 | app: "../app",
10 | },
11 | });
12 |
13 | // Start loading the main app file. Put all of
14 | // your application logic in there.
15 | requirejs(["app/main"]);
16 |
--------------------------------------------------------------------------------
/book-code-listings/chapter03/requirejs-demo/www/app/main.js:
--------------------------------------------------------------------------------
1 | define(function (require) {
2 | // Load any app-specific modules
3 | // with a relative require call,
4 | // like:
5 | var messages = require("./messages");
6 |
7 | // Load library/vendor modules using
8 | // full IDs, like:
9 | var print = require("print");
10 |
11 | print(messages.getHello());
12 | });
13 |
--------------------------------------------------------------------------------
/book-code-listings/chapter03/requirejs-demo/www/app/messages.js:
--------------------------------------------------------------------------------
1 | define(function () {
2 | return {
3 | getHello: function () {
4 | return "Hello World";
5 | },
6 | };
7 | });
8 |
--------------------------------------------------------------------------------
/book-code-listings/chapter03/requirejs-demo/www/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Hello World
8 |
9 |
10 |
--------------------------------------------------------------------------------
/book-code-listings/chapter03/requirejs-demo/www/lib/print.js:
--------------------------------------------------------------------------------
1 | define(function () {
2 | return function print(msg) {
3 | console.log(msg);
4 | };
5 | });
6 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/BasicFigure.js:
--------------------------------------------------------------------------------
1 | import { Component } from "react";
2 |
3 | class BasicFigure extends Component {
4 | render() {
5 | return (
6 | <>
7 |
8 |
9 | This is a picture of a cat.
10 |
11 |
12 | >
13 | );
14 | }
15 | }
16 |
17 | export default BasicFigure;
18 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/BasicFigureProps.js:
--------------------------------------------------------------------------------
1 | import { Component } from "react";
2 |
3 | class BasicFigureProps extends Component {
4 | render() {
5 | return (
6 | <>
7 |
8 |
13 | {this.props.caption}
14 |
15 |
16 | >
17 | );
18 | }
19 | }
20 |
21 | export default BasicFigureProps;
22 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/BoundFunction.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | class Foo extends React.Component {
4 | constructor(props) {
5 | super(props);
6 | this.message = "hello";
7 | this.handleClick = this.handleClick.bind(this);
8 | }
9 |
10 | handleClick(event) {
11 | console.log(this.message); // 'hello'
12 | }
13 |
14 | render() {
15 | return (
16 | <>
17 |
20 |
21 | >
22 | );
23 | }
24 | }
25 |
26 | export default Foo;
27 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/Counter.js:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 |
3 | function Counter() {
4 | const [count, setCount] = useState(0);
5 |
6 | return (
7 | <>
8 |
9 |
The current count is: {count}.
10 |
17 |
18 |
19 | >
20 | );
21 | }
22 |
23 | export default Counter;
24 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/CounterController.js:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 | import LeakyCounter from "./LeakyCounter";
3 |
4 | function CounterController() {
5 | const [displayCounter, setDisplayCounter] = useState(true);
6 |
7 | function toggleCounter() {
8 | setDisplayCounter(!displayCounter);
9 | }
10 |
11 | return (
12 | <>
13 |
14 | {displayCounter ? : null}
15 |
16 |
17 |
18 | >
19 | );
20 | }
21 | export default CounterController;
22 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/CreateReactClass.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import createClass from "create-react-class";
3 |
4 | const UserProfile = createClass({
5 | render() {
6 | return (
7 | <>
8 | User Profile
9 |
10 | >
11 | );
12 | },
13 | });
14 |
15 | export default UserProfile;
16 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/CutePicture.js:
--------------------------------------------------------------------------------
1 | const Joke = (props) => {
2 | const jokes = [
3 | "Did you hear about the mathematician who’s afraid of negative numbers? He’ll stop at nothing to avoid them.",
4 | "What sound does a limping turkey make? Gobble Gobble.",
5 | ];
6 | return jokes[props.id];
7 | };
8 | export default Joke;
9 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/Farm.js:
--------------------------------------------------------------------------------
1 | export default function Farm(props) {
2 | const onTheFarm = props.animals.map((animal) => {
3 | return `On his farm he had some ${animal}. `;
4 | });
5 |
6 | return (
7 |
8 |
{props.farmer} had a farm.
9 | {onTheFarm}
10 |
11 | );
12 | }
13 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/Farm/Farm.js:
--------------------------------------------------------------------------------
1 | export default function Farm(props) {
2 | return (
3 | <>
4 |
5 |
{props.farmer} had a farm.
6 |
On his farm, he had some {props.animals[0]}.
7 |
On his farm, he had some {props.animals[1]}.
8 |
On his farm, he had some {props.animals[2]}.
9 |
10 |
11 | >
12 | );
13 | }
14 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/Farm/Farms.js:
--------------------------------------------------------------------------------
1 | import Farm from "./Farm";
2 |
3 | export default function Farms() {
4 | return (
5 | <>
6 |
7 |
8 |
9 | >
10 | );
11 | }
12 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/Farm/ImprovedFarm.js:
--------------------------------------------------------------------------------
1 | export default function Farm(props) {
2 | let onHisFarm = [];
3 | if (props.animals) {
4 | onHisFarm = props.animals.map((animal, index) => (
5 | On his farm he had some {animal}.
6 | ));
7 | }
8 | return (
9 | <>
10 | {props.farmer} had a farm.
11 | {onHisFarm}
12 | >
13 | );
14 | }
15 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/Farm/ImprovedFarms.js:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 | import ImprovedFarm from "./ImprovedFarm";
3 |
4 | export default function ImprovedFarms() {
5 | const initialFarms = [
6 | {
7 | farmer: "Old McDonald",
8 | animals: ["pigs", "cows", "chickens"],
9 | },
10 | ];
11 | const [farms] = useState(initialFarms);
12 | return (
13 | <>
14 | {farms
15 | ? farms.map((farm, index) => (
16 |
21 | ))
22 | : null}
23 |
24 | >
25 | );
26 | }
27 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/FigureList.js:
--------------------------------------------------------------------------------
1 | import { Component } from "react";
2 | import BasicFigure from "./BasicFigure";
3 |
4 | class FigureList extends Component {
5 | render() {
6 | return (
7 | <>
8 |
9 |
10 |
11 |
12 | >
13 | );
14 | }
15 | }
16 | export default FigureList;
17 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/FigureListProps.js:
--------------------------------------------------------------------------------
1 | import { Component } from "react";
2 | import BasicFigureProps from "./BasicFigureProps";
3 |
4 | class FigureList extends Component {
5 | render() {
6 | return (
7 | <>
8 |
9 |
10 |
11 |
15 |
16 |
17 | >
18 | );
19 | }
20 | }
21 | export default FigureList;
22 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/Foo.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | class Foo extends React.Component {
4 | constructor(props) {
5 | super(props);
6 | this.message = "hello";
7 | this.handleClick = this.handleClick.bind(this);
8 | }
9 |
10 | handleClick(event) {
11 | console.log(this.message); // 'this' is undefined
12 | }
13 |
14 | render() {
15 | return (
16 |
19 | );
20 | }
21 | }
22 |
23 | export default Foo;
24 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/FooFunction.js:
--------------------------------------------------------------------------------
1 | export const FooFunction = (props) => Hello, World!
;
2 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/Joke.js:
--------------------------------------------------------------------------------
1 | const Joke = (props) => {
2 | const jokes = [
3 | "Did you hear about the mathematician who’s afraid of negative numbers? He’ll stop at nothing to avoid them.",
4 | "What sound does a limping turkey make? Wobble Wobble.",
5 | ];
6 | return jokes[props.id];
7 | };
8 | export default Joke;
9 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/LeakyCounter.js:
--------------------------------------------------------------------------------
1 | import { Component } from "react";
2 |
3 | class LeakyCounter extends Component {
4 | constructor() {
5 | super();
6 | this.state = { count: 0 };
7 | this.incrementCount = this.incrementCount.bind(this);
8 | }
9 |
10 | incrementCount() {
11 | this.setState({ count: this.state.count + 1 });
12 | console.log(this.state.count);
13 | }
14 |
15 | componentDidMount() {
16 | this.interval = setInterval(() => {
17 | this.incrementCount();
18 | }, 1000);
19 | }
20 |
21 | render() {
22 | return (
23 | <>
24 | The current count is: {this.state.count}.
25 |
26 | >
27 | );
28 | }
29 | }
30 | export default LeakyCounter;
31 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/LoginForm/LoginForm.js:
--------------------------------------------------------------------------------
1 | import UsernameInput from "./UsernameInput";
2 | import PasswordInput from "./PasswordInput";
3 | import LoginSubmit from "./LoginSubmit";
4 |
5 | export default function LoginForm() {
6 | return (
7 | <>
8 |
13 |
14 | >
15 | );
16 | }
17 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/LoginForm/LoginSubmit.js:
--------------------------------------------------------------------------------
1 | export default function LoginSubmit(props) {
2 | return ;
3 | }
4 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/LoginForm/PasswordInput.js:
--------------------------------------------------------------------------------
1 | export default function PasswordInput(props) {
2 | return (
3 | <>
4 |
5 |
6 | >
7 | );
8 | }
9 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/LoginForm/UsernameInput.js:
--------------------------------------------------------------------------------
1 | export default function UsernameInput(props) {
2 | return (
3 | <>
4 |
5 |
6 | >
7 | );
8 | }
9 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/NoLeakCounterController.js:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 | import NoLeakCounter from "./NoLeakCounter";
3 |
4 | function NoLeakCounterController() {
5 | const [displayCounter, setDisplayCounter] = useState(true);
6 |
7 | function toggleCounter() {
8 | setDisplayCounter(!displayCounter);
9 | }
10 |
11 | return (
12 | <>
13 |
14 | {displayCounter ? : null}
15 |
16 |
17 |
18 | >
19 | );
20 | }
21 | export default NoLeakCounterController;
22 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/PureComponent.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | class PureComponentExample extends React.PureComponent {
4 | render() {
5 | return (
6 | <>
7 | foo
8 |
9 | >
10 | );
11 | }
12 | }
13 |
14 | export default PureComponentExample;
15 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/ReactClassComponent.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | class UserProfile extends React.Component {
4 | constructor(props) {
5 | super(props);
6 | }
7 |
8 | render() {
9 | return (
10 | <>
11 | User Profile
12 |
13 | >
14 | );
15 | }
16 | }
17 |
18 | export default UserProfile;
19 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/ReactMemoExample.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | function ReactMemoExample(props) {
4 | return (
5 | <>
6 |
7 | Hi, {props.firstName}. This component returns the same thing when given
8 | the same props.
9 |
10 |
11 | >
12 | );
13 | }
14 |
15 | export default React.memo(ReactMemoExample);
16 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/ShallowCompare.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import shallowCompare from "react-addons-shallow-compare";
3 |
4 | class ShallowCompare extends React.Component {
5 | shouldComponentUpdate(nextProps, nextState) {
6 | return shallowCompare(this, nextProps, nextState);
7 | }
8 |
9 | render() {
10 | return (
11 | <>
12 | foo
13 |
14 | >
15 | );
16 | }
17 | }
18 |
19 | export default ShallowCompare;
20 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/ShoppingCart/Cart.css.js:
--------------------------------------------------------------------------------
1 | const cart = {};
2 |
3 | export default cart;
4 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/ShoppingCart/Cart.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import CartItems from "./CartItems";
3 | import DisplayTotal from "./DisplayTotal";
4 | import CheckoutButton from "./CheckoutButton";
5 | import styles from "./Cart.css.js";
6 |
7 | function Cart(props) {
8 | return (
9 | <>
10 |
11 |
Cart
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | >
21 | );
22 | }
23 |
24 | export default Cart;
25 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/ShoppingCart/CartItems.css.js:
--------------------------------------------------------------------------------
1 | export default {
2 | cartItems: {},
3 | };
4 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/ShoppingCart/CartItems.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import Item from "./Item.js";
3 |
4 | function CartItems(props) {
5 | const [inCart] = useState(props.inCart);
6 |
7 | let ItemList = inCart.map((item) => {
8 | return (
9 |
10 | item:
11 |
12 | );
13 | });
14 |
15 | return (
16 |
17 | Here are the items in your cart:
18 | {ItemList}
19 |
20 | );
21 | }
22 | CartItems.defaultProps = {
23 | inCart: [{ id: 1, title: "React JS Foundations", price: 5 }],
24 | };
25 |
26 | export default CartItems;
27 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/ShoppingCart/CheckoutButton.js:
--------------------------------------------------------------------------------
1 | function CheckoutButton(props) {
2 | return ;
3 | }
4 |
5 | export default CheckoutButton;
6 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/ShoppingCart/DisplayTotal.js:
--------------------------------------------------------------------------------
1 | function DisplayTotal(props) {
2 | return total: $
;
3 | }
4 |
5 | export default DisplayTotal;
6 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/ShoppingCart/Item.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | function Item(props) {
4 | const handleClick = (e) => {
5 | this.props.removeFromCart(props.id);
6 | };
7 |
8 | return (
9 |
10 | {props.title} - {props.price}
11 |
12 |
13 | );
14 | }
15 |
16 | export default Item;
17 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/ThingsThatAreFunny.js:
--------------------------------------------------------------------------------
1 | export default function ThingsThatAreFunny(props) {
2 | return (
3 | <>
4 | Here are some funny things.
5 | {props.children}
6 |
7 | >
8 | );
9 | }
10 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/ThingsThatILike.js:
--------------------------------------------------------------------------------
1 | import ThingsThatAreFunny from "./ThingsThatAreFunny";
2 | import Joke from "./Joke";
3 |
4 | export default function ThingsILike(props) {
5 | return (
6 | <>
7 |
8 |
9 | -
10 |
11 |
12 | -
13 |
14 |
15 |
16 |
17 |
18 | >
19 | );
20 | }
21 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/UnboundFunction.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | class Foo extends React.Component {
4 | constructor(props) {
5 | super(props);
6 | this.message = "hello";
7 | }
8 |
9 | handleClick(event) {
10 | console.log(this.message); // 'this' is undefined
11 | }
12 |
13 | render() {
14 | return (
15 | <>
16 |
19 |
20 | >
21 | );
22 | }
23 | }
24 |
25 | export default Foo;
26 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/WelcomeMessage.js:
--------------------------------------------------------------------------------
1 | function WelcomeMessage() {
2 | return (
3 | <>
4 | Welcome!
5 |
6 | >
7 | );
8 | }
9 | export default WelcomeMessage;
10 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/WelcomeTitle.js:
--------------------------------------------------------------------------------
1 | import WelcomeMessage from "./WelcomeMessage";
2 |
3 | function WelcomeTitle() {
4 | return (
5 | <>
6 |
7 |
8 | >
9 | );
10 | }
11 |
12 | export default WelcomeTitle;
13 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/clone-element/App.js:
--------------------------------------------------------------------------------
1 | import NavBar from "./NavBar";
2 | import NavItem from "./NavItem";
3 |
4 | function App(props) {
5 | return (
6 | <>
7 | {
9 | console.log("clicked");
10 | }}
11 | >
12 |
13 |
14 |
15 |
16 |
17 | >
18 | );
19 | }
20 |
21 | export default App;
22 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/clone-element/NavBar.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | function NavBar(props) {
4 | return (
5 |
6 | {React.Children.map(props.children, (child) => {
7 | return React.cloneElement(child, {
8 | onClick: props.onClick,
9 | });
10 | })}
11 |
12 | );
13 | }
14 |
15 | export default NavBar;
16 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/clone-element/NavBarChildren.js:
--------------------------------------------------------------------------------
1 | function NavBar(props) {
2 | return (
3 | <>
4 | {props.children}
5 |
6 | >
7 | );
8 | }
9 | export default NavBar;
10 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/clone-element/NavBarCloneChildren.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | function NavBar(props) {
4 | return (
5 | <>
6 |
7 | {React.Children.map(props.children, (child) => {
8 | return React.cloneElement(child, {
9 | onClick: props.onClick,
10 | });
11 | })}
12 |
13 |
14 | >
15 | );
16 | }
17 |
18 | export default NavBar;
19 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/clone-element/NavBarPassingOnClick.js:
--------------------------------------------------------------------------------
1 | import NavBar from "./NavBar";
2 | import NavItem from "./NavItem";
3 |
4 | function App(props) {
5 | return (
6 | <>
7 | {
9 | console.log("clicked");
10 | }}
11 | >
12 |
13 |
14 |
15 |
16 |
17 | >
18 | );
19 | }
20 |
21 | export default App;
22 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/clone-element/NavBarUsingOnClick.js:
--------------------------------------------------------------------------------
1 | function NavItem(props) {
2 | return (
3 | <>
4 |
5 |
6 | >
7 | );
8 | }
9 |
10 | export default NavItem;
11 |
--------------------------------------------------------------------------------
/book-code-listings/chapter04/clone-element/NavItem.js:
--------------------------------------------------------------------------------
1 | function NavItem(props) {
2 | return (
3 | <>
4 |
5 |
6 | >
7 | );
8 | }
9 | export default NavItem;
10 |
--------------------------------------------------------------------------------
/book-code-listings/chapter06/BorderBox.js:
--------------------------------------------------------------------------------
1 | import PropTypes from "prop-types";
2 |
3 | function BorderBox(props) {
4 | return (
5 | <>
6 | {props.children}
7 |
8 | >
9 | );
10 | }
11 |
12 | BorderBox.propTypes = {
13 | children: PropTypes.element.isRequired,
14 | };
15 |
16 | export default BorderBox;
17 |
--------------------------------------------------------------------------------
/book-code-listings/chapter06/Contact.js:
--------------------------------------------------------------------------------
1 | import PropTypes from "prop-types";
2 |
3 | function Contact(props) {
4 | return (
5 | <>
6 |
7 | {props.fullName}: {props.phone}
8 |
9 |
10 | >
11 | );
12 | }
13 |
14 | const isPhoneNumber = function (props, propName, componentName) {
15 | const regex = /^(\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4}$/;
16 |
17 | if (!regex.test(props[propName])) {
18 | return new Error(
19 | `Invalid prop ${propName} passed to ${componentName}. Expected a phone number.`
20 | );
21 | }
22 | };
23 |
24 | Contact.propTypes = {
25 | fullName: PropTypes.string,
26 | phone: isPhoneNumber,
27 | };
28 |
29 | export default Contact;
30 |
--------------------------------------------------------------------------------
/book-code-listings/chapter06/CounterClass.js:
--------------------------------------------------------------------------------
1 | import { Component } from "react";
2 |
3 | class CounterClass extends Component {
4 | constructor(props) {
5 | super(props);
6 | this.state = { count: 0 };
7 | this.increment = this.increment.bind(this);
8 | }
9 | increment() {
10 | this.setState({ count: this.state.count + 1 });
11 | }
12 | render() {
13 | return (
14 | <>
15 |
16 |
17 | >
18 | );
19 | }
20 | }
21 | export default CounterClass;
22 |
--------------------------------------------------------------------------------
/book-code-listings/chapter06/CounterClass3.js:
--------------------------------------------------------------------------------
1 | import { Component } from "react";
2 |
3 | class CounterClass3 extends Component {
4 | constructor(props) {
5 | super(props);
6 | this.state = { count: 0 };
7 | this.testCount = 0;
8 | this.incrementTwice = this.incrementTwice.bind(this);
9 | }
10 |
11 | incrementTwice() {
12 | this.setState({ count: this.state.count + 1 });
13 | this.testCount++;
14 | this.setState({ count: this.state.count + 1 });
15 | this.testCount++;
16 | console.log("Count should be: " + this.testCount);
17 | }
18 |
19 | render() {
20 | return (
21 | <>
22 |
23 |
24 | >
25 | );
26 | }
27 | }
28 | export default CounterClass3;
29 |
--------------------------------------------------------------------------------
/book-code-listings/chapter06/DisplayPrimaryColors.js:
--------------------------------------------------------------------------------
1 | import PropTypes from "prop-types";
2 |
3 | function DisplayPrimaryColor(props) {
4 | return (
5 | <>
6 | You picked: {props.primaryColor}
7 |
8 | >
9 | );
10 | }
11 |
12 | DisplayPrimaryColor.propTypes = {
13 | primaryColor: PropTypes.oneOf(["red", "green", "blue"]),
14 | };
15 |
16 | export default DisplayPrimaryColor;
17 |
--------------------------------------------------------------------------------
/book-code-listings/chapter06/Dog.js:
--------------------------------------------------------------------------------
1 | import { Component } from "react";
2 |
3 | class Dog extends Component {
4 | render() {
5 | return A Dog: {this.props.firstName}
;
6 | }
7 | }
8 |
9 | export default Dog;
10 |
--------------------------------------------------------------------------------
/book-code-listings/chapter06/FamilyTree.js:
--------------------------------------------------------------------------------
1 | import { Component } from "react";
2 | import { PropTypes } from "prop-types";
3 | import Person from "./Person";
4 |
5 | class FamilyTree extends Component {
6 | render() {
7 | return (
8 | <>
9 |
10 |
{this.props.father.firstName}
11 |
12 |
13 | >
14 | );
15 | }
16 | }
17 |
18 | FamilyTree.propTypes = {
19 | father: PropTypes.instanceOf(Person).isRequired,
20 | pet: PropTypes.elementType,
21 | };
22 |
23 | export default FamilyTree;
24 |
--------------------------------------------------------------------------------
/book-code-listings/chapter06/IncrementTwice.js:
--------------------------------------------------------------------------------
1 | import { Component } from "react";
2 |
3 | class CounterClass extends Component {
4 | constructor(props) {
5 | super(props);
6 | this.state = { count: 0 };
7 | this.countCopy = 0;
8 | this.incrementTwice = this.incrementTwice.bind(this);
9 | }
10 |
11 | incrementTwice() {
12 | this.setState({ count: this.state.count + 1 });
13 | this.countCopy++;
14 | this.setState({ count: this.state.count + 1 });
15 | this.countCopy++;
16 | console.log("Count should be: " + this.countCopy);
17 | }
18 |
19 | render() {
20 | return ;
21 | }
22 | }
23 | export default CounterClass;
24 |
--------------------------------------------------------------------------------
/book-code-listings/chapter06/Map.js:
--------------------------------------------------------------------------------
1 | function Map(props) {
2 | return (
3 |
4 | {props.latitude}
5 |
6 | {props.longitude}
7 |
8 | );
9 | }
10 | export default Map;
11 |
--------------------------------------------------------------------------------
/book-code-listings/chapter06/NewsFeed2.js:
--------------------------------------------------------------------------------
1 | import { Component } from "react";
2 |
3 | class NewsFeed2 extends Component {
4 | state = {
5 | date: new Date(),
6 | headlines: [],
7 | };
8 |
9 | render() {
10 | return (
11 | <>
12 | Headlines for {this.state.date.toLocaleString()}
13 | ...
14 |
15 | >
16 | );
17 | }
18 | }
19 |
20 | export default NewsFeed2;
21 |
--------------------------------------------------------------------------------
/book-code-listings/chapter06/NewsFeed3.js:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 |
3 | function NewsFeed3(props) {
4 | const [date, setDate] = useState(new Date());
5 | const [headlines, setHeadlines] = useState([]);
6 |
7 | return (
8 | <>
9 | Headlines for {date.toLocaleString()}
10 | ...
11 |
12 | >
13 | );
14 | }
15 |
16 | export default NewsFeed3;
17 |
--------------------------------------------------------------------------------
/book-code-listings/chapter06/NewsFeed4.js:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 |
3 | function NewsFeed4(props) {
4 | const [state] = useState({ date: new Date(), headlines: [] });
5 |
6 | return (
7 | <>
8 | Headlines for {state.date.toLocaleString()}
9 | ...
10 |
11 | >
12 | );
13 | }
14 |
15 | export default NewsFeed4;
16 |
--------------------------------------------------------------------------------
/book-code-listings/chapter06/Person.js:
--------------------------------------------------------------------------------
1 | export default function Person(firstName) {
2 | this.firstName = firstName;
3 | }
4 |
--------------------------------------------------------------------------------
/book-code-listings/chapter06/Reminders/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
4 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
5 | sans-serif;
6 | -webkit-font-smoothing: antialiased;
7 | -moz-osx-font-smoothing: grayscale;
8 | }
9 |
10 | code {
11 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
12 | monospace;
13 | }
14 |
--------------------------------------------------------------------------------
/book-code-listings/chapter06/Reminders/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom";
3 | import "./index.css";
4 | import App from "./App";
5 | import reportWebVitals from "./reportWebVitals";
6 |
7 | ReactDOM.render(
8 |
9 |
10 | ,
11 | document.getElementById("root")
12 | );
13 |
14 | // If you want to start measuring performance in your app, pass a function
15 | // to log results (for example: reportWebVitals(console.log))
16 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
17 | reportWebVitals();
18 |
--------------------------------------------------------------------------------
/book-code-listings/chapter06/Reminders/reportWebVitals.js:
--------------------------------------------------------------------------------
1 | const reportWebVitals = (onPerfEntry) => {
2 | if (onPerfEntry && onPerfEntry instanceof Function) {
3 | import("web-vitals").then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
4 | getCLS(onPerfEntry);
5 | getFID(onPerfEntry);
6 | getFCP(onPerfEntry);
7 | getLCP(onPerfEntry);
8 | getTTFB(onPerfEntry);
9 | });
10 | }
11 | };
12 |
13 | export default reportWebVitals;
14 |
--------------------------------------------------------------------------------
/book-code-listings/chapter06/RemindersClass/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
4 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
5 | sans-serif;
6 | -webkit-font-smoothing: antialiased;
7 | -moz-osx-font-smoothing: grayscale;
8 | }
9 |
10 | code {
11 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
12 | monospace;
13 | }
14 |
--------------------------------------------------------------------------------
/book-code-listings/chapter06/RemindersClass/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom";
3 | import "./index.css";
4 | import App from "./App";
5 | import reportWebVitals from "./reportWebVitals";
6 |
7 | ReactDOM.render(
8 |
9 |
10 | ,
11 | document.getElementById("root")
12 | );
13 |
14 | // If you want to start measuring performance in your app, pass a function
15 | // to log results (for example: reportWebVitals(console.log))
16 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
17 | reportWebVitals();
18 |
--------------------------------------------------------------------------------
/book-code-listings/chapter06/RemindersClass/reportWebVitals.js:
--------------------------------------------------------------------------------
1 | const reportWebVitals = (onPerfEntry) => {
2 | if (onPerfEntry && onPerfEntry instanceof Function) {
3 | import("web-vitals").then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
4 | getCLS(onPerfEntry);
5 | getFID(onPerfEntry);
6 | getFCP(onPerfEntry);
7 | getLCP(onPerfEntry);
8 | getTTFB(onPerfEntry);
9 | });
10 | }
11 | };
12 |
13 | export default reportWebVitals;
14 |
--------------------------------------------------------------------------------
/book-code-listings/chapter06/SiteLink.js:
--------------------------------------------------------------------------------
1 | function SiteLink(props) {
2 | return {props.linkName};
3 | }
4 |
5 | export default SiteLink;
6 |
--------------------------------------------------------------------------------
/book-code-listings/chapter06/SiteLinkNode.js:
--------------------------------------------------------------------------------
1 | import PropTypes from "prop-types";
2 |
3 | function SiteLink(props) {
4 | return (
5 | <>
6 | {props.linkName}
7 |
8 | >
9 | );
10 | }
11 |
12 | SiteLink.propTypes = {
13 | linkName: PropTypes.node,
14 | };
15 |
16 | export default SiteLink;
17 |
--------------------------------------------------------------------------------
/book-code-listings/chapter06/StoreList.js:
--------------------------------------------------------------------------------
1 | function StoreList(props) {
2 | return (
3 |
4 | {props.latitude}
5 |
6 | {props.longitude}
7 |
8 | );
9 | }
10 | export default StoreList;
11 |
--------------------------------------------------------------------------------
/book-code-listings/chapter06/StoresNearYou.js:
--------------------------------------------------------------------------------
1 | import Map from "./Map";
2 | import StoreList from "./StoreList";
3 |
4 | function StoresNearYou(props) {
5 | return (
6 | <>
7 |
8 |
12 |
13 |
14 |
18 |
19 |
20 | >
21 | );
22 | }
23 |
24 | export default StoresNearYou;
25 |
--------------------------------------------------------------------------------
/book-code-listings/chapter06/StoresNearYou1.js:
--------------------------------------------------------------------------------
1 | import Map from "./Map";
2 | import StoreList from "./StoreList";
3 |
4 | function StoresNearYou1(props) {
5 | return (
6 | <>
7 |
8 |
12 |
13 |
14 |
18 |
19 |
20 | >
21 | );
22 | }
23 |
24 | export default StoresNearYou1;
25 |
--------------------------------------------------------------------------------
/book-code-listings/chapter06/StoresNearYou2.js:
--------------------------------------------------------------------------------
1 | import Map from "./Map";
2 | import StoreList from "./StoreList";
3 |
4 | function StoresNearYou3(props) {
5 | const latitude = props.latitude || "37.3230";
6 | const longitude = props.longitude || "122.0322";
7 |
8 | return (
9 | <>
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | >
18 | );
19 | }
20 |
21 | export default StoresNearYou3;
22 |
--------------------------------------------------------------------------------
/book-code-listings/chapter06/StoresNearYou5.js:
--------------------------------------------------------------------------------
1 | import Map from "./Map";
2 | import StoreList from "./StoreList";
3 |
4 | function StoresNearYou(props) {
5 | return (
6 | <>
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | >
15 | );
16 | }
17 |
18 | StoresNearYou.defaultProps = {
19 | latitude: "37.3230",
20 | longitude: "122.0322",
21 | };
22 |
23 | export default StoresNearYou;
24 |
--------------------------------------------------------------------------------
/book-code-listings/chapter06/WelcomeClass.js:
--------------------------------------------------------------------------------
1 | import PropTypes from "prop-types";
2 | import { Component } from "react";
3 |
4 | class WelcomeClass extends Component {
5 | static propTypes = {
6 | firstName: PropTypes.string,
7 | };
8 |
9 | render() {
10 | return (
11 | <>
12 | Welcome, {this.props.firstName}!
13 |
14 | >
15 | );
16 | }
17 | }
18 |
19 | export default WelcomeClass;
20 |
--------------------------------------------------------------------------------
/book-code-listings/chapter06/WelcomeMessage.js:
--------------------------------------------------------------------------------
1 | import PropTypes from "prop-types";
2 |
3 | function WelcomeMessage(props) {
4 | return (
5 | <>
6 | Welcome back, {props.firstName}!
7 |
8 | >
9 | );
10 | }
11 |
12 | WelcomeMessage.propTypes = {
13 | firstName: PropTypes.string,
14 | };
15 |
16 | export default WelcomeMessage;
17 |
--------------------------------------------------------------------------------
/book-code-listings/chapter07/CoffeeMachine.js:
--------------------------------------------------------------------------------
1 | import { Component } from "react";
2 |
3 | class CoffeeMachine extends Component {
4 | constructor(props) {
5 | super(props);
6 | this.state = {
7 | brewing: false,
8 | };
9 | this.toggleBrewing = this.toggleBrewing.bind(this);
10 | }
11 |
12 | toggleBrewing = function () {
13 | this.setState({ brewing: !this.state.brewing });
14 | };
15 |
16 | render() {
17 | return (
18 | <>
19 | The Coffee Maker is {this.state.brewing ? "on" : "off"}.
20 |
21 |
22 | >
23 | );
24 | }
25 | }
26 |
27 | export default CoffeeMachine;
28 |
--------------------------------------------------------------------------------
/book-code-listings/chapter07/ColorWheel.js:
--------------------------------------------------------------------------------
1 | import { Component } from "react";
2 |
3 | class ColorWheel extends Component {
4 | state = { currentColor: "#ff0000" };
5 |
6 | changeColor = (e) => {
7 | this.setState({ currentColor: e.target.value });
8 | };
9 |
10 | render() {
11 | const wheelStyle = {
12 | width: "200px",
13 | height: "200px",
14 | borderRadius: "50%",
15 | backgroundColor: this.state.currentColor,
16 | };
17 |
18 | return (
19 | <>
20 |
21 |
22 |
23 | >
24 | );
25 | }
26 | }
27 |
28 | export default ColorWheel;
29 |
--------------------------------------------------------------------------------
/book-code-listings/chapter07/ColorWheel4.js:
--------------------------------------------------------------------------------
1 | import { Component } from "react";
2 |
3 | class ColorWheel extends Component {
4 | state = { currentColor: "#ff0000" };
5 |
6 | changeColor = (e) => {
7 | this.setState({ currentColor: e.target.value });
8 | };
9 |
10 | render() {
11 | const wheelStyle = {
12 | width: "200px",
13 | height: "200px",
14 | borderRadius: "50%",
15 | backgroundColor: this.state.currentColor,
16 | };
17 |
18 | return (
19 | <>
20 |
21 |
22 |
23 | >
24 | );
25 | }
26 | }
27 |
28 | export default ColorWheel;
29 |
--------------------------------------------------------------------------------
/book-code-listings/chapter07/EventListener.js:
--------------------------------------------------------------------------------
1 | function MyForm(props) {
2 | return (
3 | <>
4 |
9 |
10 | >
11 | );
12 | }
13 | export default MyForm;
14 |
--------------------------------------------------------------------------------
/book-code-listings/chapter07/EventObject.js:
--------------------------------------------------------------------------------
1 | function LogInput() {
2 | const logChange = (e) => {
3 | console.dir(e);
4 | };
5 | return (
6 | <>
7 |
8 |
9 | >
10 | );
11 | }
12 |
13 | export default LogInput;
14 |
--------------------------------------------------------------------------------
/book-code-listings/chapter07/EventObject2.js:
--------------------------------------------------------------------------------
1 | function LogInput() {
2 | const logChange = (e) => {
3 | console.dir(e);
4 | };
5 | return (
6 | <>
7 | {
9 | logChange(e);
10 | }}
11 | />
12 |
13 | >
14 | );
15 | }
16 |
17 | export default LogInput;
18 |
--------------------------------------------------------------------------------
/book-code-listings/chapter07/ScreenDoor.js:
--------------------------------------------------------------------------------
1 | import { Component } from "react";
2 |
3 | class ScreenDoor extends Component {
4 | constructor(props) {
5 | super(props);
6 | this.state = {
7 | isOpen: true,
8 | };
9 | }
10 | render() {
11 | return (
12 | <>
13 |
16 |
17 | >
18 | );
19 | }
20 | }
21 |
22 | export default ScreenDoor;
23 |
--------------------------------------------------------------------------------
/book-code-listings/chapter07/Search.js:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 |
3 | function Search(props) {
4 | const [term, setTerm] = useState("");
5 |
6 | const updateTerm = (searchTerm) => {
7 | setTerm(searchTerm);
8 | };
9 |
10 | return (
11 | <>
12 | {
16 | updateTerm(e.target.value);
17 | }}
18 | />
19 |
20 | You're searching for: {term}
21 |
22 | >
23 | );
24 | }
25 |
26 | export default Search;
27 |
--------------------------------------------------------------------------------
/book-code-listings/chapter07/WarningButton.js:
--------------------------------------------------------------------------------
1 | function WarningButton() {
2 | return (
3 | <>
4 |
5 |
12 |
13 |
14 |
15 | >
16 | );
17 | }
18 |
19 | function CodeAndText(){
20 | return(
21 | <>
22 |
23 |
24 | >
25 | )
26 | }
27 |
28 | export default WarningButton;
29 |
--------------------------------------------------------------------------------
/book-code-listings/chapter07/index.js:
--------------------------------------------------------------------------------
1 | export { default as MyForm } from "./EventListener";
2 | export { default as EventProps } from "./EventProps";
3 | export { default as WarningButton } from "./WarningButton";
4 | export { default as ScreenDoor } from "./ScreenDoor";
5 | export { default as SearchTerm } from "./Search";
6 | export { default as CoffeeMachine } from "./CoffeeMachine";
7 | export { default as ColorWheel } from "./ColorWheel";
8 | export { default as ColorWheel2 } from "./ColorWheel2";
9 | export { default as ColorWheel3 } from "./ColorWheel3";
10 | export { default as ColorWheel4 } from "./ColorWheel4";
11 | export { default as EventObject } from "./EventObject";
12 | export { default as EventObject2 } from "./EventObject2";
13 |
--------------------------------------------------------------------------------
/book-code-listings/chapter08/Controlled1.js:
--------------------------------------------------------------------------------
1 | function SignUp(props) {
2 | return (
3 | <>
4 |
8 |
9 | >
10 | );
11 | }
12 |
13 | export default SignUp;
14 |
--------------------------------------------------------------------------------
/book-code-listings/chapter08/Controlled2.js:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 |
3 | function SignUp(props) {
4 | const [emailAddress, setEmailAddress] = useState("");
5 |
6 | const handleChange = (e) => {
7 | setEmailAddress(e.target.value);
8 | };
9 |
10 | return (
11 | <>
12 |
18 |
19 | Your email address: {emailAddress}
20 |
21 | >
22 | );
23 | }
24 |
25 | export default SignUp;
26 |
--------------------------------------------------------------------------------
/book-code-listings/chapter08/SearchForm/SearchBox.js:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 | import SearchInput from "./SearchInput";
3 | import SearchResults from "./SearchResults";
4 |
5 | function SearchBox() {
6 | const [searchTerm, setSearchTerm] = useState();
7 |
8 | return (
9 | <>
10 |
11 |
12 |
13 | >
14 | );
15 | }
16 | export default SearchBox;
17 |
--------------------------------------------------------------------------------
/book-code-listings/chapter08/SearchForm/SearchInput.js:
--------------------------------------------------------------------------------
1 | function SearchInput(props) {
2 | const handleChange = (e) => {
3 | props.setSearchTerm(e.target.value);
4 | };
5 |
6 | return (
7 | <>
8 |
12 |
13 | >
14 | );
15 | }
16 |
17 | export default SearchInput;
18 |
--------------------------------------------------------------------------------
/book-code-listings/chapter08/SearchForm/SearchResults.js:
--------------------------------------------------------------------------------
1 | function SearchResults(props) {
2 | return (
3 | <>
4 | You're searching for: {props.searchTerm}
5 |
6 | >
7 | );
8 | }
9 |
10 | export default SearchResults;
11 |
--------------------------------------------------------------------------------
/book-code-listings/chapter08/SignUpForm.js:
--------------------------------------------------------------------------------
1 | function SignUpForm(props) {
2 | const handleSubmit = (e) => {
3 | e.preventDefault();
4 | props.commitFormData();
5 | };
6 |
7 | return (
8 | <>
9 |
13 |
14 | >
15 | );
16 | }
17 |
18 | export default SignUpForm;
19 |
--------------------------------------------------------------------------------
/book-code-listings/chapter08/SizeSelect.js:
--------------------------------------------------------------------------------
1 | function SizeSelect(props) {
2 | return (
3 | <>
4 |
11 |
12 | >
13 | );
14 | }
15 |
16 | export default SizeSelect;
17 |
--------------------------------------------------------------------------------
/book-code-listings/chapter08/TermsOfUse.js:
--------------------------------------------------------------------------------
1 | function TermsOfUse(props) {
2 | return (
3 | <>
4 |
9 |
10 | >
11 | );
12 | }
13 |
14 | export default TermsOfUse;
15 |
--------------------------------------------------------------------------------
/book-code-listings/chapter08/Uncontrolled1.js:
--------------------------------------------------------------------------------
1 | function SignUp(props) {
2 | return (
3 | <>
4 |
8 |
9 | >
10 | );
11 | }
12 |
13 | export default SignUp;
14 |
--------------------------------------------------------------------------------
/book-code-listings/chapter09/CreateRefClass.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 |
3 | class TextReader extends Component {
4 | constructor(props) {
5 | super(props);
6 | this.textView = React.createRef();
7 | }
8 | render() {
9 | return (
10 | <>
11 |
12 |
13 | >
14 | );
15 | }
16 | }
17 |
18 | export default TextReader;
19 |
--------------------------------------------------------------------------------
/book-code-listings/chapter09/CreateRefFunction.js:
--------------------------------------------------------------------------------
1 | import { useRef } from "react";
2 |
3 | function TextReader(props) {
4 | const textView = useRef(null);
5 |
6 | return (
7 | <>
8 |
9 |
10 | >
11 | );
12 | }
13 |
14 | export default TextReader;
15 |
--------------------------------------------------------------------------------
/book-code-listings/chapter09/TextReader.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 |
3 | class TextReader extends Component {
4 | constructor(props) {
5 | super(props);
6 | this.textView = React.createRef();
7 | }
8 |
9 | componentDidMount() {
10 | this.textView.current.focus();
11 | }
12 |
13 | render() {
14 | return (
15 | <>
16 |
21 |
22 | >
23 | );
24 | }
25 | }
26 |
27 | export default TextReader;
28 |
--------------------------------------------------------------------------------
/book-code-listings/chapter09/TextReaderCallback2.js:
--------------------------------------------------------------------------------
1 | import { Component } from "react";
2 |
3 | class TextReaderCallback extends Component {
4 | constructor(props) {
5 | super(props);
6 | this.textView = null;
7 |
8 | this.focusTextView = () => {
9 | if (this.textView) this.textView.focus();
10 | };
11 | }
12 |
13 | componentDidMount() {
14 | this.focusTextView();
15 | }
16 |
17 | render() {
18 | return (
19 | <>
20 |