fullstack react book r19

678 880 0
  • Loading ...
1/678 trang
Tải xuống

Thông tin tài liệu

Ngày đăng: 20/05/2017, 11:32

Fullstack React The Complete Book on ReactJS and Friends Anthony Accomazzo, Ari Lerner, David Guttman, Nate Murray, Clay Allsopp and Tyler McGinnis © 2015 - 2016 Fullstack.io Contents Book Revision Prerelease Bug Reports Chat With The Community! Be notified of updates via Twitter We’d love to hear from you! 1 1 1 Your first React Web Application Building Product Hunt Setting up your development environment Code editor Node.js and npm Browser Special instruction for Windows users Ensure IIS is installed Getting started Sample Code Previewing the application Prepare the app Our first component React.createClass() JSX The developer console Babel ReactDOM.render() Our second component Making Product data-driven The data model Using props Rendering multiple products React the vote (your app’s first interaction) Propagating the event Using state Setting state with this.setState() 1 1 2 3 10 11 12 13 14 15 18 18 18 22 25 25 30 31 CONTENTS Updating state Congratulations! Components A time-logging app Getting started Previewing the app Prepare the app Breaking the app into components The steps for building React apps Step 2: Build a static version of the app TimersDashboard EditableTimer TimerForm ToggleableTimerForm Timer Render the app Try it out Step 3: Determine what should be stateful State criteria Applying the criteria Step 4: Determine in which component each piece of state should live The list of timers and properties of each timer Whether or not the edit form of a timer is open Visibility of the create form Step 5: Hard-code initial states Adding state to TimersDashboard Receiving props in EditableTimerList Props vs state Adding state to EditableTimer Timer and TimerForm remain stateless Adding state to ToggleableTimerForm Step 6: Add inverse data flow TimerForm ToggleableTimerForm TimersDashboard Updating timers Adding editability to Timer Updating EditableTimer Updating EditableTimerList Defining onEditFormSubmit() in TimersDashboard Deleting timers Adding the event handler to Timer 33 34 36 36 37 37 37 40 47 49 49 51 52 53 54 55 55 57 57 58 59 59 60 60 60 60 62 62 63 64 64 65 66 68 69 71 72 72 73 74 78 78 CONTENTS Routing through EditableTimer Routing through EditableTimerList Implementing the delete function in TimersDashboard Adding timing functionality Adding a forceUpdate() interval to Timer Try it out Add start and stop functionality Add timer action events to Timer Create TimerActionButton Run the events through EditableTimer and EditableTimerList Try it out Methodology review 78 79 79 81 82 83 83 83 84 85 87 88 Components & Servers Introduction Preparation server.js The Server API text/html endpoint JSON endpoints Playing with the API Loading state from the server Try it out client Fetch Sending starts and stops to the server Sending creates, updates, and deletes to the server Give it a spin Next up 90 90 90 90 91 92 92 93 96 98 98 99 102 105 106 106 JSX and the Virtual DOM React Uses a Virtual DOM Why Not Modify the Actual DOM? What is a Virtual DOM? Virtual DOM Pieces ReactElement Experimenting with ReactElement Rendering Our ReactElement Adding Text (with children) ReactDOM.render() JSX JSX Creates Elements JSX Attribute Expressions 108 108 108 108 109 110 110 112 114 115 116 116 117 CONTENTS JSX Conditional Child Expressions JSX Boolean Attributes JSX Comments JSX Spread Syntax JSX Gotchas JSX Summary References 118 118 119 119 120 123 123 Advanced Component Configuration with props, state, and children Intro ReactComponent Creating ReactComponents - createClass or ES6 Classes render() Returns a ReactElement Tree Getting Data into render() props are the parameters PropTypes Default props with getDefaultProps() context state Using state: Building a Custom Radio Button getInitialState() Thinking About State Stateless Components Switching to Stateless Stateless Encourages Reuse Talking to Children Components with props.children React.Children.map() & React.Children.forEach() React.Children.toArray() ReactComponent Static Methods Summary References 124 124 125 125 125 126 127 128 129 129 135 135 140 142 143 144 146 146 149 150 151 152 152 Forms Forms 101 Preparation The Basic Button Events and Event Handlers Back to the Button Text Input Accessing User Input With refs Using User Input Uncontrolled vs Controlled Components Accessing User Input With state 153 153 153 154 156 157 159 160 162 165 166 CONTENTS Multiple Fields On Validation Adding Validation to Our App Creating the Field Component Using our new Field Component Remote Data Building the Custom Component Adding CourseSelect Separation of View and State Async Persistence Redux Form Component Connect the Store Form Modules formsy-react react-input-enhancements tcomb-form winterfell react-redux-form 168 172 173 177 181 186 187 192 195 196 202 206 210 212 212 212 213 213 213 Using Webpack with create-react-app JavaScript modules create-react-app Exploring create-react-app public/index.html package.json src/ index.js Booting the app Webpack basics Making modifications to the sample app Hot reloading Auto-reloading Creating a production build Ejecting Buckle up Using create-react-app with an API server The completed app How the app is organized The server Client Concurrently Using the Webpack development proxy 214 214 216 217 218 219 221 223 227 229 235 235 236 237 240 241 243 243 246 247 248 249 252 CONTENTS Webpack at large 254 When to use Webpack/create-react-app 255 Unit Testing Writing tests without a framework Preparing Modash Writing the first spec The assertEqual() function What is Jest? Using Jest expect() The first Jest test for Modash The other truncate() spec The rest of the specs Testing strategies for React applications Integration vs Unit Testing Shallow rendering Enzyme Testing a basic React component with Enzyme Setup The App component The first spec for App More assertions for App Using beforeEach Simulating a change Clearing the input field Simulating a form submission Writing tests for the food lookup app FoodSearch Exploring FoodSearch Writing FoodSearch.test.js In initial state A user has typed a value into the search field Mocking with Jest Mocking Client The API returns results The user clicks on a food item The API returns empty result set Further reading 256 256 257 260 262 266 266 267 270 271 272 274 274 275 275 276 276 277 281 285 288 291 295 297 304 306 308 312 314 316 320 322 328 333 337 341 Routing 344 What’s in a URL? 344 React Router’s core components 346 CONTENTS Building the components of react-router The completed app Building Match Building Link Building Router Building Redirect Using react-router More Match Using Miss Dynamic routing with React Router The completed app The server’s API Starting point of the app Using URL params Propagating pathnames as props Dynamic menu items with Link Supporting authenticated routes The Client library Implementing login MatchWhenLoggedIn, a higher-order component Redirect state Recap Further Reading Intro to Flux and Redux Why Flux? Flux is a Design Pattern Flux overview Flux implementations Redux Redux’s key ideas Building a counter Preparation Overview The counter’s actions Incrementing the counter Decrementing the counter Supporting additional parameters on actions Building the store Try it out The core of Redux Next up The beginnings of a chat app 348 348 350 357 363 368 373 374 378 380 381 384 386 392 399 404 408 409 410 416 420 422 422 423 423 423 424 425 425 425 426 426 427 428 429 430 432 434 438 439 440 440 CONTENTS Previewing State Actions Building the reducer() Initializing state Handling the ADD_MESSAGE action Handling the DELETE_MESSAGE action Subscribing to the store createStore() in full Connecting Redux to React Using store.getState() Using store.subscribe() Using store.dispatch() The app’s components Preparing app.js The App component The MessageInput component The MessageView component ReactDOM.render() Next up 440 443 443 444 444 444 447 450 452 455 455 455 456 456 457 458 459 462 463 464 Intermediate Redux Preparation Using createStore() from the redux library Try it out Representing messages as objects in state Updating ADD_MESSAGE Updating DELETE_MESSAGE Updating the React components Introducing threads Supporting threads in initialState Supporting threads in the React components Modifying App Turning MessageView into Thread Try it out Adding the ThreadTabs component Updating App Creating ThreadTabs Try it out Supporting threads in the reducer Updating ADD_MESSAGE in the reducer Updating the MessageInput component Try it out 465 465 466 467 467 468 470 471 473 475 477 478 479 480 482 482 483 484 486 486 491 492 Appendix A: PropTypes 649 const Component = React.createClass({ propTypes: { totalCount: React.PropTypes.number }, // }) Passing in a number, we must pass it as a JavaScript value or the value of a variable using braces: var x = 20; boolean To specify a prop should be a boolean (true or false), we can use React.PropTypes.bool const Component = React.createClass({ propTypes: { on: React.PropTypes.bool }, // }) To use a boolean in a JSX expression, we can pass it as a JavaScript value var isOn = true; A trick for using booleans to show or hide content is to use the && expression For instance, inside our Component.render() function, if we want to show content only when the on proptype is true, we can so like: javascript render: function() { return ( {this.props.on && This component is on} ) } Appendix A: PropTypes 650 function We can pass a function as a prop as well To define a prop to be a function, we can use React.PropTypes.func Often times when we write a Form component, we’ll pass a function as a prop to be called when the form is submitted (i.e onSubmit()) It’s common to define a prop as a required function on a component const Component = React.createClass({ propTypes: { onComplete: React.PropTypes.func }, // }) We can pass a function as a prop by using the JavaScript expression syntax, like so: const x = function(name) {}; const fn = value => alert("Value: " + value); object We can require a prop should be a JavaScript object through the React.PropTypes.object: const Component = React.createClass({ propTypes: { user: React.PropTypes.object }, // }) Sending an object through as a prop, we’ll need to use the JavaScript expression {} syntax: Appendix A: PropTypes 651 const user = { name: 'Ari' } object shape React allows us to define the shape of an object we expect to receive by using React.PropTypes.shape() The React.PropTypes.shape() function accepts an object with a list of key-value pairs that dictate the keys an object is expected to have as well as the value type: 10 const Component = React.createClass({ propTypes: { user: React.PropTypes.shape({ name: React.PropTypes.string, friends: React.PropTypes.arrayOf(React.PropTypes.object), age: React.PropTypes.number }) }, // }) multiple types Sometimes we don’t know in advance what kind a particular prop will be, but we can accept one or other type React gives us the propTypes of oneOf() and oneOfType() for these situations Using oneOf() requires that the propType be a discrete value of values, for instance to require a component to specify a log level value: const Component = React.createClass({ propTypes: { level: React.PropTypes.oneOf(['debug', 'info', 'warning', 'error']) }, // }) Using oneOfType() says that a prop can be one of any number of types For instance, a phone number may either be passed to a component as a string or an integer: Appendix A: PropTypes 652 const Component = React.createClass({ propTypes: { phoneNumber: React.PropTypes.oneOfType([ React.PropTypes.number, React.PropTypes.string ]) }, // }) instanceOf We can dictate that a component must be an instance of a JavaScript class using React.PropTypes.instanceOf() as the value of the propType: const Component = React.createClass({ propTypes: { user: React.PropTypes.instanceOf(User) }, // }) We’ll use the JavaScript expression syntax to pass in a particular prop const User = function(name) { this.name = name; return this; }; const ari = new User('Ari'); array On occasion we’ll want to send in an array as a prop To set an array, we’ll use the React.PropTypes.array as the value Appendix A: PropTypes 653 const Component = React.createClass({ propTypes: { authors: React.PropTypes.array }, // }) Sending an object through as a prop, we’ll need to use the JavaScript expression {} syntax: const users = [ {name: 'Ari'} {name: 'Anthony'} ]; array of type React allows us to dictate the type of values each member of an array should be using React.PropTypes.arrayOf() const Component = React.createClass({ propTypes: { authors: React.PropTypes.arrayOf(React.PropTypes.object) }, // }) We’ll use the JavaScript expression syntax {} to pass in an array: Appendix A: PropTypes 654 const users = [ {name: 'Ari'} {name: 'Anthony'} ]; node We can also pass anything that can be rendered, such as numbers, string, DOM elements, arrays, or fragments that contain them using the React.PropTypes.node const Component = React.createClass({ propTypes: { icon: React.PropTypes.node }, // }) Passing a node as a prop is straightforward as well Passing a node as a value is often useful when requiring a component to have children or setting a custom element For instance, if we want to allow our user to pass in either the name of an icon or a custom component, we can use the node propType const icon = element React’s flexibility allows us to pass another React element in as a prop as well by using the React.PropTypes.element: Appendix A: PropTypes 655 const Component = React.createClass({ propTypes: { customHeader: React.PropTypes.element }, // }) We can build our components so that the interface they allow our users to specify a custom component For instance, we might have a component who’s responsibility is to output a list of elements Without custom components, we would have to build a separate React component for each type of list we want to render (which might be appropriate, depending on the behavior of the element) By passing a component type, we can reuse the component For instance, a list component might look like: 10 11 12 13 14 15 16 17 18 const List = React.createClass({ propTypes: { listComponent: PropTypes.element, list: PropTypes.array }, renderListItem: function(item, i) { const Component = this.props.listComponent || "li"; return React.createElement(Component, this.props, item) }, render: function() { const list = this.props.list; return ( {list.map(this.renderListItem)} ) } }); We can use this list component with or without specifying a custom component: Appendix A: PropTypes 10 656 const Item = React.createClass({ render: function() { return ( {this.props.children} ) } }) any type React also allows us to specify that a prop must be present, regardless of it’s type We can this by using the React.PropTypes.any validator const Component = React.createClass({ propTypes: { mustBePresent: React.PropTypes.any }, // }) Optional & required props All props are considered optional unless otherwise specified To require a prop be passed to a component and validated, we can append every propType validation with isRequired For instance, if we must have a function to get called after some action when a Loading component has completed, we can specify it like this: 10 const Loading = React.createClass({ propTypes: { // Optional props: onStart: React.PropTypes.func, // Required props: onComplete: React.PropTypes.func.isRequired, name: React.PropTypes.string.isRequired }, // }) Appendix A: PropTypes 657 custom validator React allows us to specify a custom validation function for all of the other situations where the default validation functions don’t cover it In order to run a write a custom validation we’ll specify a function that accepts arguments: The props passed to the component The propName being validated The componentName we’re validating against If our validation passes, we can run through the function and return anything The validation function will only fail if an Error object is raised (i.e new Error()) For instance, if we have a loader that accepts validated users, we can run a custom function against the prop 10 11 const Component = React.createClass({ propTypes: { user: function(props, propName, componentName) { const user = props[propName]; if (!user.isValid()) { return new Error('Invalid user'); } } }, // }) Appendix B: Tools It takes an ecosystem to build a web app This appendix describes a few tools that we use when developing our React apps Curl cURL¹⁵⁸ is a standard, popular tool for performing HTTP requests on the commandline It comes pre-installed on many systems Being able to use cURL effectively is an important skill to have as a web developer Curl is often the first tool many people turn to for debugging or automating HTTP requests In order to use curl you will need some understanding of the HTTP protocol If you’re unfamiliar with HTTP, checkout A Beginner’s Guide to HTTP and REST¹⁵⁹ and The HttpWatch Guide to HTTP¹⁶⁰ A GET Request If you have curl installed on your system, you can make a basic request like this: curl http://google.com A POST Request You can also use cURL to mimic submitting a form by using a POST request Here is how you can submit a POST request to GraphQL hub¹⁶¹: curl -H 'Content-Type:application/graphql' -XPOST https://www.graphqlhub.com\ /graphql?pretty=true -d '{ hn { topStories(limit: 2) { title url } } }' Notice that there are three options here, passed as “flags”: ¹⁵⁸https://curl.haxx.se/ ¹⁵⁹http://code.tutsplus.com/tutorials/a-beginners-guide-to-http-and-rest net-16340 ¹⁶⁰https://www.httpwatch.com/httpgallery/introduction/ ¹⁶¹https://www.graphqlhub.com 659 Appendix B: Tools • -H - states that we want to pass a header In this case, we’re passing ht HTTP header ContentType as application/graphql • -XPOST - states that we want to send a POST request • -d - states that the string that follows is the POST body In this case, it is a GraphQL query that fetches the top posts from Hacker News Chrome “Copy as cURL” Chrome has a powerful feature that lets you copy any HTTP operation a cURL request To this: Copy as cURL in Chrome Open up the Chrome Developer Tools Click on the “Network” Tab Navigate with your browser / perform the operation you want to copy Locate your HTTP request in the list of requests Right click the request and pick “Copy as cURL” Paste your request into your shell Appendix B: Tools 660 When you paste the command, you’ll notice that it has a lot of “noise” The browser sends quite a lot of headers! Not all of them are always necessary for your request to succeed, but it’s a good starting point This can be especially helpful when you have authentication cookies stored in your browser and you need to debug a protected request curl 'https://www.fullstackreact.com/assets/vendor/functions.js' -H 'if-none\ -match: W/"5dd95509e78d11579fc427e9f41889d6"' -H 'accept-encoding: gzip, deflate\ , sdch' -H 'accept-language: en-US,en;q=0.8' -H 'user-agent: Mozilla/5.0 (Macint\ osh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.\ 2623.75 Safari/537.36' -H 'accept: */*' -H 'cache-control: max-age=0' -H 'author\ ity: www.fullstackreact.com' -H 'cookie: cfduid=d309889bd8e027d878c2e16e0176e7\ 64d1463427161; _ga=GA1.2.135748265.1463427163; _gat=1' -H 'if-modified-since: Tu\ e, 15 Mar 2016 03:37:56 GMT' -H 'referer: https://www.fullstackreact.com/' com\ pressed Though not technically identical, the essential, trimmed down version of this request could be: curl 'https://www.fullstackreact.com/assets/vendor/functions.js' More Resources If you learn more about cURL, checkout: • The official curl tutorial¹⁶² • This Github API curl tutorial¹⁶³ ¹⁶²https://curl.haxx.se/docs/httpscripting.html ¹⁶³https://gist.github.com/joyrexus/85bf6b02979d8a7b0308 Changelog Revision 19 - 2016-12-20 • Added “Routing” Chapter! Revision 18 - 2016-11-22 • Improved Windows support • Updated code to react-15.4.1 • Bug fixes Revision 17 - 2016-11-04 • Updated code to work in Windows without Cygwin (PowerShell) • Added Windows setup instructions to the book • Bumped Babel versions Revision 16 - 2016-10-12 • Added “Unit Testing” Chapter! Revision 15 - 2016-10-05 • Added “Using Webpack with create-react-app” Chapter! Revision 14 - 2016-08-26 • Added “Forms” Chapter! Revision 13 - 2016-08-02 • Updated code to react-15.3.0 Revision 12 - 2016-07-26 • Updated code to react-15.2.1 Changelog Revision 11 - 2016-07-08 • Updated code to react-15.2.0 Revision 10 - 2016-06-24 • Updated code to react-15.1.0 Revision - 2016-06-21 • Added “Writing a GraphQL Server” Chapter Revision - 2016-06-02 • Added “Intermediate Redux” Chapter • Added “Using Presentational and Container Components with Redux” Chapter Revision - 2016-05-13 • Added “Using GraphQL” chapter • Updated all code to react-15.0.2 Revision - 2016-05-13 • Added “Configuring Components” chapter • Added “PropTypes” appendix Revision - 2016-04-25 • Added “Intro to Flux and Redux” chapter Revision - 2016-04-22 • Added “JSX and the Virtual DOM” chapter Revision - 2016-04-08 • Upgraded all code to react-15.0.1 662 Changelog 663 Revision - 2016-03-16 • • • • Significant rewrites to Ch “First React Application” to make it clearer / better flow of thought Various bugfixes Improvements to code style Updated diagrams Revision - 2016-02-14 Initial version of the book Contains: • Ch Your first React Web Application • Ch Components • Ch Components & Servers
- Xem thêm -

Xem thêm: fullstack react book r19, fullstack react book r19, fullstack react book r19

Mục lục

Xem thêm

Gợi ý tài liệu liên quan cho bạn

Nhận lời giải ngay chưa đến 10 phút Đăng bài tập ngay