└── README.md /README.md: -------------------------------------------------------------------------------- 1 | # React Cheatsheet 2 | Set of basic functionalities from React in one place. 3 | 4 | Cheatsheet has been created by https://foreach.pl trainers for training participants. 5 | 6 | **Check also other Cheatsheets:** 7 | 8 | [Angular](https://github.com/delprzemo/angular-cheatsheet) 9 | 10 | [TypeScript](https://github.com/delprzemo/typescript-cheatsheet) 11 | 12 | 13 | # Table of Contents 14 | 15 | 16 | * [Basic React commands](#Basic-React-commands) 17 | * [JSX](#JSX) 18 | * [Injection JS into HTML](#Injection-JS-into-HTML) 19 | * [Element declaration](#Element-declaration) 20 | * [Function injection](#Function-injection) 21 | * [Attributes](#Attributes) 22 | * [Fragments](#Fragments) 23 | * [References](#References) 24 | * [Components](#Components) 25 | * [Function component](#Function-component) 26 | * [Class component](#Class-component) 27 | * [Events](#Events) 28 | * [Conditional element](#Conditional-element) 29 | * [List of elements](#List-of-elements) 30 | * [Content projection](#Content-projection) 31 | * [Higher order component](#Higher-order-component) 32 | * [Routing](#Routing) 33 | * [Nested routing](#Nested-routing) 34 | * [Routing with parameters](#Routing-with-parameters) 35 | * [Authentication](#Authentication) 36 | * [State and life cycle](#State-and-life-cycle) 37 | * [State](#State) 38 | * [Life cycle](#Life-cycle) 39 | * [Forms](#Forms) 40 | * [Http requests](#Http-requests) 41 | * [Tests](#Tests) 42 | * [Interaction](#Interaction) 43 | * [Mocking http](#Mocking-http) 44 | * [Mocking components](#Mocking-components) 45 | * [Context](#Context) 46 | * [Hooks](#Hooks) 47 | * [Basic hooks](#Basic-hooks) 48 | * [Other hooks](#Other-hooks) 49 | * [Custom hook](#Custom-hook) 50 | * [TypeScript in React](#TypeScript-in-React) 51 | * [Add to project commands](#Add-to-project-commands) 52 | * [Add type for custom DOM element](#Add-type-for-custom-DOM-element) 53 | * [Interview questions](#Interview-questions) 54 | 55 | 56 | 57 | Basic React commands 58 | ================= 59 | 60 | | Command | Notes | 61 | | ------------- | ------------- | 62 | | npx create-react-app {app name} | Create new React app | 63 | | npm run build | Build React app - create a folder with files ready for deployment | 64 | | npm start | Run project locally | 65 | | npm test | run tests in React app | 66 | | npm eject | remove the single build dependency from your project | 67 | 68 | 69 | 70 | JSX 71 | ================= 72 | 73 | JSX allows us to write HTML elements in JavaScript and place them in the DOM. Basically, it converts HTML tags into react elements. 74 | 75 | ## Injection JS into HTML 76 | 77 | ```jsx 78 |  const value = 'Hello world'; 79 |  return (
{value}
); 80 | ``` 81 | 'Hello world' will be injected and displayed inside `
` element 82 | 83 | ## Element declaration 84 | 85 | ```jsx 86 | const value = 'Hello World'; 87 | const element = {value}
; 88 | return (element); 89 | ``` 90 | We can assign specific DOM fragments to a particular variable (element above) and then (re)use it everywhere. 91 | 92 | ## Function injection 93 | 94 | ```jsx 95 | function addNumbers(x1, x2) { 96 | return x1 + x2; 97 | } 98 | const element = {addNumbers(2, 5)} 99 | ``` 100 | Not only string values can be injected into DOM. The result of the above case will be div with 7 inside it as addNumbers was injected into an element. 101 | 102 | ## Attributes 103 | ```jsx 104 |   const avatarUrl = "img/picture.jpg" 105 |   const element = ; 106 | ``` 107 | JavaScript code can be also called for DOM element properties/events 108 | 109 | ## Fragments 110 | JSX syntax must have one top parent HTML element. When we don't want to pack our HTML into (for example) one div or other elements then we can use `fragment` which won't be rendered in our HTML 111 | 112 | Example: 113 | ```jsx 114 | 115 | val1 116 | val2 117 | 118 | ``` 119 | 120 | or 121 | 122 | ```jsx 123 | <> 124 | val1 125 | val2 126 | 127 | 128 | ``` 129 | 130 | ## References 131 | We can refer to html element from JS 132 | 133 | 1. Declare a reference 134 | ```js 135 | this.element = React.createRef(); 136 | ``` 137 | 138 | 2. Assign a reference to element 139 | ```jsx 140 | 141 | ``` 142 | 143 | 3. Use reference to interact with element 144 | ```js 145 | this.element.current.focus(); 146 | ``` 147 | 148 | Tip: References works for the class component but not for function component (unless you use useRef hook, see [Other hooks](https://github.com/delprzemo/react-cheatsheet#other-hooks "other-hooks") ) 149 | 150 | Components 151 | ================= 152 | 153 | "React lets you define components as classes or functions. Components defined as classes currently provide more features" 154 | 155 | ## Function component 156 | 157 | Sample component: 158 | ```js 159 | function App() { 160 |   return 
Hello World
; 161 | } 162 | export default App; 163 | ``` 164 | 165 | Sample component with parameters: 166 | 167 | ```js 168 | function Welcome(props) { 169 |     return 

Hello, {props.name}

; 170 | } 171 | ``` 172 | ```jsx 173 | 174 | ``` 175 | 176 | ## Class component 177 | 178 | Sample component: 179 | ```js 180 | class App extends React.Component  { 181 |   render() { 182 |     return 
Hello World
; 183 |   } 184 | } 185 | export default App; 186 | ``` 187 | 188 | Sample component with the parameters: 189 | 190 | ```js 191 | class Welcome extends React.Component  { 192 |   render() { 193 |     return 
Hello {this.props.name}
; 194 |   } 195 | } 196 | export default App; 197 | ``` 198 | ```jsx 199 | 200 | ``` 201 | 202 | ## Events 203 | 204 | Sample `onClick` event in an element: 205 | ```jsx 206 |  Click me  207 | ``` 208 | 209 | onClick function: 210 | ```jsx 211 | onClick(e) { 212 | e.preventDefault(); 213 | // some logic here 214 | } 215 | 216 | ``` 217 | 218 | **Access to "this" inside event:** 219 | 220 | There are a few ways to achieve that: 221 | 222 | 1. bind this 223 | ```js 224 | this.onClick = this.onClick.bind(this); 225 | ``` 226 | 227 | 2. Arrow function. For arrow function, you don't have to perform binding because arrow functions are performing this binding by themselves by referring to this with `_this` variable `_this = this` 228 | ```js 229 | onClick = (e) => { 230 |     e.preventDefault(); 231 |     console.log(this); 232 | } 233 | ``` 234 | 235 | or 236 | 237 | ```jsx 238 |   this.onClick(e)}> Click me 239 | ``` 240 | 241 | **Child event** 242 | 243 | We can call a function in parent component from the child component. 244 | 245 | Child component (somewhere in code): 246 | ```js 247 | this.props.onChange(val1, val2,...) 248 | ``` 249 | 250 | Parent component: 251 | ```jsx 252 | 253 | ``` 254 | 255 | ```js 256 | function hasChanged(val1, val2,...) { 257 | // some logic here 258 | } 259 | ``` 260 | 261 | ## Conditional element 262 | 263 | Show element depending on the implemented condition 264 | 265 | **Option 1:** 266 | ```js 267 | function SomeElement(props) { 268 | const show = props.isShowed; 269 | if(show) { 270 | return 
Here is element
; 271 | }          272 | } 273 | ``` 274 | then: 275 | ```jsx 276 | 277 | ``` 278 | 279 | **Option 2:** 280 | ```js 281 | let element;       282 | if(this.state.isShown) { 283 | element  = 
Here is element
; 284 | }  285 | ``` 286 | 287 | and then use the element variable in jsx 288 | 289 | **Option 3:** 290 | ```jsx 291 | {this.state.isShow  ? 
Here is element
 : 'No element'} 292 | ``` 293 | 294 | **Option 4:** 295 | ```jsx 296 | {this.state.isShow &&
Here is element
} 297 | ``` 298 | 299 | ## List of elements 300 | 301 | The recommended way to show a list of the same components is to use the "map" function. Example: 302 | ```js 303 | const numbers = [1, 2, 3, 4, 5]; 304 | const listItems = numbers.map((numer, index) => 305 |    306 |     {number} 307 |    308 | ); 309 | 310 | ``` 311 | Then just use `listItems` element in your JSX DOM. 312 | Please note `key` property inside - it is obligatory to identify particular row in list. 313 | 314 | ## Content projection 315 | 316 | Content projection is injecting some HTML from parent component to child component 317 | 318 | Example: 319 | 320 | Parent component: 321 | ```jsx 322 |

Hello world

323 | ``` 324 | 325 | Child (MyElement) component: 326 | ```jsx 327 |
328 | {this.props.children} 329 |
330 | ``` 331 | 332 | `

Hello world

` will be injected to place where `{this.props.children}` has been used, so MyElement will look like: 333 | 334 | ```jsx 335 |
336 |

Hello world

337 |
338 | ``` 339 | 340 | ## Higher order component 341 | Create a parameterized component in order to reuse it in different ways. 342 | 343 | Example: 344 | ```jsx 345 | const myHoc = settings => WrappedComponent => { 346 |     return class DecoratingComponent extends React.Component { 347 |         render() { 348 |             return () 349 |         } 350 |     } 351 | } 352 | ``` 353 | 354 | Usage: 355 | ```jsx 356 | const MyWrappedComponent = myHoc('test')(SomeComponent); 357 | 358 | ``` 359 | `test` will be injected into className 360 | 361 | 362 | Routing 363 | ================= 364 | The Router will be described with react-router-dom library usage, which is often recommended. 365 | 366 | Install: 367 | ``` 368 | npm install react-router-dom 369 | ``` 370 | 371 | Sample presenting an area where components matching to current URL will be rendered: 372 | 373 | ```jsx 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | ``` 383 | 384 | Link changing current url: 385 | 386 | ```jsx 387 | List 388 | ``` 389 | 390 | Tip: Route and Link need to be in same Router element 391 | 392 | ## Nested routing 393 | 394 | Parent: 395 | ```jsx 396 | 397 | ``` 398 | 399 | SomeComponent: 400 | ```js 401 | function  SomeComponent({ match }) { 402 |     return ( 403 |          404 |              405 |                  406 |              407 |          408 |     ) 409 | } 410 | ``` 411 | 412 | ## Routing with parameters 413 | 414 | ```jsx 415 | 416 | ``` 417 | 418 | and then in SomeComponent we have access to: 419 | 420 | ```jsx 421 | {match.params.id} 422 | ``` 423 | 424 | ## Authentication 425 | 426 | Good idea is to create a custom Route component that will show specific component only when our authentication logic is passed: 427 | 428 | ```jsx 429 | function PrivateRoute({ component: Component, ...rest }) { 430 |     return ( 431 |          (_isAuthentictedLogic_) ? 432 |             () : 433 |             ( 434 |             )} 435 |         /> 436 |     ); 437 | } 438 | ``` 439 | 440 | Then instead of Route use PrivateRoute 441 | 442 | ```jsx 443 | 444 | ``` 445 | 446 | 447 | State and life cycle 448 | ================= 449 | 450 | ## State 451 | The state decides about the update to a component’s object. When state changes, the component is re-rendered. 452 | 453 | Declaring initial state: 454 | ```js 455 | constructor() { 456 | this.state = { userId: 2, userName: "Jannice"}; 457 | } 458 | ``` 459 | 460 | Using state: 461 | ```jsx 462 |
{this.state.userName}
463 | ``` 464 | 465 | Updating state: 466 | ```js 467 | this.setState({ userId: 3, userName: "Tom"}); 468 | ``` 469 | After setState component will be re-rendered 470 | 471 | ## Life cycle 472 | 473 | | Life cycle | Notes | 474 | | ------------- | ------------- | 475 | | componentDidMount | Called at the beginning of component life - when a component has been rendered | 476 | | componentWillUnmount | This method is called before the unmounting of the component takes place. | 477 | | componentWillUpdate | Before re-rendering component (after change) | 478 | | componentDidUpdate | After re-rendering component (after change) | 479 | | componentDidCatch | Called when an error has been thrown| 480 | | shouldComponentUpdate | Determines whether a component should be updated after a change or not | 481 | | getDerivedStateFromProps | Called at the beginning of component life and when props/state will change | 482 | | getSnapshotBeforeUpdate| Called just before rerendering component - in order to save state| 483 | 484 | **Note** Deprecation alert for componentWillUnmount and componentWillUpdate. This can cause memory leaks for server rendering. 485 | 486 | 487 | Example: 488 | ```jsx 489 | componentDidMount() { 490 | console.log("componentDidMount") 491 | // some logic here 492 | } 493 | 494 | componentWillUnmount() { 495 | console.log("componentWillUnmount") 496 | // some logic here 497 | } 498 | ``` 499 | 500 | Forms 501 | ================= 502 | 503 | Sample form: 504 | 505 | ```js 506 | onValueChange  = (event) => { 507 |     this.setState({ value:  event.target.value  }); 508 | } 509 | ``` 510 | ```js 511 | onSubmit = (e) => { 512 | e.preventDefault(); 513 | // Submit logic 514 | } 515 | 516 | ``` 517 | ```jsx 518 | 519 |      523 |      524 |      525 | 526 | ``` 527 | 528 | Validation is described here: https://webfellas.tech/#/article/5 529 | 530 | Http requests 531 | ================= 532 | 533 | There are a lot of ways to communicate with our backend API. One of them is to use Axios library. 534 | 535 | Install: 536 | `npm install axios` 537 | 538 | Example with GET: 539 | ```js 540 | axios.get('/user', { 541 | params: {ID: 12345} 542 | }).then(function (response) { 543 | //some logic here 544 | }) 545 | .catch(function (error) { 546 | //some logic here 547 | }) 548 | .finally(function () { 549 | //some logic here 550 | });  551 | ``` 552 | 553 | Example with POST: 554 | ```js 555 | axios.post('/user', { 556 |     firstName: 'Fred', 557 | id: 2 558 | }).then(function (response) { 559 | //some logic here 560 | }) 561 | .catch(function (error) { 562 | //some logic here 563 | }); 564 | ``` 565 | 566 | Example with async call: 567 | ```js 568 | const response = await axios.get('/user?ID=12345'); 569 | ``` 570 | 571 | Tests 572 | ================= 573 | 574 | Useful libs: 575 | 576 | `npm install --save-dev jest` to run tests 577 | 578 | `npm install --save-dev @testing-library/react` set of functions that may be useful for tests in React 579 | 580 | Sample tests: 581 | 582 | ```jsx 583 | let container = null; 584 | beforeEach(() => { 585 |   container = document.createElement("div"); 586 |   document.body.appendChild(container); 587 | }); 588 | afterEach(() => { 589 |   unmountComponentAtNode(container); 590 |   container.remove(); 591 |   container = null; 592 | }); 593 | it("renders menu with Help", () => { 594 |   act(() => { 595 |     render(, container); 596 |   }); 597 |   expect(container.textContent).toBe("Some text inside"); 598 | }); 599 | 600 | ``` 601 | 602 | ## Interaction 603 | 604 | Click on element: 605 | ```js 606 | import { fireEvent } from '@testing-library/react' 607 | ``` 608 | ```js 609 | fireEvent.click(container.querySelector('.some-class)); 610 | ``` 611 | 612 | Change value in input: 613 | ```js 614 | fireEvent.change(container.querySelector('.some-class)), { 615 |     target: { value: "12345" } 616 | }); 617 | ``` 618 | 619 | Check if element contains class 620 | ```js 621 | expect(someEl.classList.contains('disabled')).toBe(false); 622 | ``` 623 | 624 | ## Mocking http 625 | 626 | `npm install axios-mock-adapter --save-dev` 627 | 628 | Example: 629 | ```js 630 | var axios = require('axios'); 631 | var MockAdapter = require('axios-mock-adapter'); 632 | var mock = new MockAdapter(axios); 633 | 634 | ``` 635 | ```js 636 | mock.onGet('/users').reply(200, { 637 |   users: [ 638 |     { id: 1, name: 'John Smith' } 639 |   ] 640 | }); 641 | ``` 642 | 643 | With specific parameter 644 | ```js 645 | mock.onGet('/users', { params: { searchText: 'John' } }).reply() 646 | ``` 647 | 648 | ## Mocking components 649 | Example: 650 | ```js 651 | jest.mock("./SomeComponent", () => { 652 |   return function DummyComponent(props) { 653 |     return ( 654 |        655 |         here is square 656 |        657 |     ); 658 |   }; 659 | }); 660 | 661 | ``` 662 | 663 | Context 664 | ================= 665 | 666 | Context is a "bag" for some data common for node of components. 667 | 668 | Declare context: 669 | ```js 670 | import React from 'react'; 671 | export const ColorContext = React.createContext('red'); 672 | ``` 673 | 'red' is default value 674 | 675 | Create context and distribute it to child component: 676 | ```jsx 677 | const { Provider } = ColorContext; 678 | return ( 679 |      680 |      681 |      682 | ); 683 | ``` 684 | 685 | Use it in child component: 686 | ```js 687 | const { Consumer } = ColorContext; 688 | return ( 689 | 690 | {value => 
{value}
} 691 |
692 | ) 693 | ``` 694 | 695 | Use it in child component outside render function: 696 | ```js 697 | static contextType = ColorContext; 698 | let value = this.context.value 699 | ``` 700 | 701 | Hooks 702 | ================= 703 | Hooks let us use in functions React features dedicated previously for only classes, like state. 704 | 705 | 706 | ## Basic hooks 707 | 708 | **useState hook** 709 | 710 | Can replace state managment 711 | ```js 712 | const [count, setCount] = useState(0); 713 | ``` 714 | `count` can be used to read data 715 | 716 | `0` is the default value for count 717 | 718 | `setCount(10)` is a function to change count state value 719 | 720 | **useEffect hook** 721 | 722 | Can replace `componentDidMount`, `componentDidUpdate`, `componentWillUnmount` and other life cycle component events 723 | 724 | Instead of using componentDidMount, componentDidUpdate we can use useEffect hook like this: 725 | ```js 726 | useEffect(() => { 727 |     document.title = `Clicked ${count}`; 728 | }); 729 | ``` 730 | 731 | In order to act as componentWillUnmount: 732 | ```js 733 | useEffect(() => { 734 |     return () => {/*unsubscribe*/}; 735 | }); 736 | ``` 737 | 738 | 739 | **useContext hook** 740 | 741 | Hooks for context implementation. See [Context](https://github.com/delprzemo/react-cheatsheet#context "context") 742 | 743 | Parent: 744 | ```jsx 745 | const CounterContext = React.createContext(counter); 746 | 747 | function App() { 748 | return ( 749 | 750 | 751 | 752 | ); 753 | } 754 | ``` 755 | 756 | Child: 757 | ```jsx 758 | const counter = useContext(CounterContext); 759 | ``` 760 | 761 | ## Other hooks 762 | 763 | | Hook | Usage | Notes | 764 | | ------------- | ------------- | ------------- | 765 | | useReducer | const [state, dispatch] = useReducer(reducer, initialArg, init); | Used for redux | 766 | | useCallback | const memoizedCallback = useCallback(() => {doSomething(a, b);},[a, b],); | Returns a memoized callback | 767 | | useMemo | const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]); | Returns a memoized value. | 768 | | useRef | const refContainer = useRef(initialValue); | Hooks for element reference | 769 | | useDebugValue | useDebugValue(value) | Display information in React DevTools | 770 | 771 | ## Custom hook 772 | Custom hooks can be created. 773 | Sample implementation: 774 | ```jsx 775 | function useColor(initialColor) { 776 |     const [color, changeColor] = useState(initialColor); 777 |     function change(color) { 778 |         changeColor(color); 779 |     } 780 |     useEffect(() => { 781 |         console.log('Color changed'); 782 |     }); 783 |     return [color, change]; 784 | } 785 | 786 | ``` 787 | 788 | 789 | TypeScript in React 790 | ================= 791 | 792 | ## Add to project commands 793 | 794 | `npx create-react-app my-app --typescript` - new app with TypeScript 795 | 796 | `npm install --save typescript @types/node @types/react @types/react-dom @types/jest` - add TypeScript to existing project 797 | 798 | `npx tsc --init` - init tsconfig 799 | 800 | ## Add type for custom DOM element 801 | 802 | ```ts 803 | declare namespace JSX { 804 |     interface IntrinsicElements {foo: any} 805 | } 806 | ; // ok 807 | ; // error 808 | ``` 809 | 810 | 811 | Interview questions 812 | ================= 813 | 814 | **Q: How can we declare the component??** 815 | 816 | A: Use class extending React.Component or use function with React.FC type returning JSX. 817 | 818 | **Q: What is a difference between function component and class component?** 819 | 820 | A: Components defined as classes currently provide more features. Anyway, hooks can change that. 821 | 822 | **Q: In what type of component can we use hooks?** 823 | 824 | A: Function component 825 | 826 | **Q: How can we inject some HTML from parent component to child component?** 827 | 828 | A: Using content projection - > this.props.children will keep parent html element. 829 | See [Content projection](https://github.com/delprzemo/react-cheatsheet#content-projection "content-projection") 830 | 831 | **Q: Describe useEffect hook** 832 | 833 | A: UseEffect can replace componentDidMount, componentDidUpdate, componentWillUnmount and other life cycle component events. 834 | See [Basic hooks](https://github.com/delprzemo/react-cheatsheet#basic-hooks "Basic-hooks") 835 | 836 | **Q: What is the difference between state and props??** 837 | 838 | A: The state decides about the update to a component’s object. When state changes, the component is re-rendered. 839 | Props are parameters passed from parent component to child component. 840 | 841 | **Q: What is a higher-order component??** 842 | 843 | A: Basically its's parameterized component. It allows reusing of a particular component in many ways. 844 | Sample implementation: 845 | ```jsx 846 | const myHoc = settings => WrappedComponent => { 847 | return class DecoratingComponent extends React.Component { 848 | render() { 849 | return (
) 850 | } 851 | } 852 | } 853 | ``` 854 | 855 | usage: 856 | ```jsx 857 | const MyWrappedComponent = myHoc('test')(SomeComponent); 858 | 859 | ``` 860 | 861 | **Q: What is JSX?** 862 | 863 | A: JSX allows us to write HTML elements in JavaScript and place them in the DOM. Basically, it converts HTML tags into react elements. See [JSX](https://github.com/delprzemo/react-cheatsheet#JSX "JSX") 864 | 865 | **Q: How can we create new react app?** 866 | 867 | A: Using command `npx create-react-app {app name}` 868 | 869 | **Q: What will be the result of `npm eject`?** 870 | 871 | A: Webpack for React application won't be handled automatically anymore. We will have access to Webpack configuration files in order to customize it to our needs. 872 | 873 | 874 | --------------------------------------------------------------------------------