├── .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 |
14 | 15 | 16 | 17 |
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 | 14 | 15 | 16 | ); 17 | } 18 | 19 | export default SearchBox; 20 | -------------------------------------------------------------------------------- /book-code-listings/chapter03/SearchBox/SearchInput.js: -------------------------------------------------------------------------------- 1 | function SearchInput(props) { 2 | return ( 3 | 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 | a cat 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 | {this.props.caption} 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 |
9 | 10 | 11 | 12 | 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 |
    5 | 6 | 7 | 8 |
    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 |
    5 | 6 | 7 |
    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 |
    13 | 17 |
    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 |
    10 | 11 | 12 |
    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 |