├── .gitignore ├── LICENSE ├── README.md ├── _config.yml ├── fiber └── book │ └── Intro.md └── stack ├── book ├── Intro.md ├── Part-0.md ├── Part-1.md ├── Part-10.md ├── Part-11.md ├── Part-12.md ├── Part-13.md ├── Part-14.md ├── Part-2.md ├── Part-3.md ├── Part-4.md ├── Part-5.md ├── Part-6.md ├── Part-7.md ├── Part-8.md └── Part-9.md ├── images ├── 0 │ ├── jsx-to-vdom.svg │ ├── mounting-scheme-1-big.svg │ ├── mounting-scheme-1-small.svg │ ├── part-0-A.svg │ ├── part-0-B.svg │ ├── part-0-C.svg │ └── part-0.svg ├── 1 │ ├── communication-channel.svg │ ├── part-1-A.svg │ ├── part-1-B.svg │ ├── part-1-C.svg │ ├── part-1.svg │ └── transaction.svg ├── 2 │ ├── part-2-A.svg │ ├── part-2-B.svg │ ├── part-2-C.svg │ └── part-2.svg ├── 3 │ ├── part-3-A.svg │ ├── part-3-B.svg │ ├── part-3-C.svg │ └── part-3.svg ├── 4 │ ├── part-4-A.svg │ ├── part-4-B.svg │ ├── part-4-C.svg │ └── part-4.svg ├── 5 │ ├── part-5-A.svg │ ├── part-5-B.svg │ ├── part-5-C.svg │ └── part-5.svg ├── 6 │ ├── overall-mounting-scheme.svg │ ├── part-6-A.svg │ ├── part-6-B.svg │ ├── part-6-C.svg │ └── part-6.svg ├── 7 │ ├── mounting-parts-C.jpg │ ├── mounting-parts-C.svg │ ├── part-7-A.svg │ ├── part-7-B.svg │ ├── part-7-C.svg │ └── part-7.svg ├── 8 │ ├── part-8-A.svg │ ├── part-8-B.svg │ ├── part-8-C.svg │ └── part-8.svg ├── 9 │ ├── part-9-A.svg │ ├── part-9-B.svg │ ├── part-9-C.svg │ ├── part-9.svg │ └── set-state-update-start.svg ├── 10 │ ├── part-10-A.svg │ ├── part-10-B.svg │ ├── part-10-C.svg │ └── part-10.svg ├── 11 │ ├── part-11-A.svg │ ├── part-11-B.svg │ ├── part-11-C.svg │ └── part-11.svg ├── 12 │ ├── part-12-A.svg │ ├── part-12-B.svg │ ├── part-12-C.svg │ └── part-12.svg ├── 13 │ ├── part-13-A.svg │ ├── part-13-B.svg │ ├── part-13-C.svg │ └── part-13.svg ├── 14 │ ├── children-update.svg │ ├── part-14-A.svg │ ├── part-14-B.svg │ ├── part-14-C.svg │ ├── part-14.svg │ ├── updating-parts-C.jpg │ └── updating-parts-C.svg ├── intro │ ├── all-page-stack-reconciler-25-scale.jpg │ ├── all-page-stack-reconciler.svg │ ├── files-scheme.svg │ ├── modules-per-platform-scheme.svg │ └── modules-src-path.svg ├── mounting-c-parts │ ├── C-0-mounting-parts.svg │ ├── C-1-mounting-parts.svg │ ├── C-2-mounting-parts.svg │ ├── C-3-mounting-parts.svg │ ├── C-4-mounting-parts.svg │ ├── C-5-mounting-parts.svg │ ├── C-6-mounting-parts.svg │ └── C-7-mounting-parts.svg └── updating-c-parts │ ├── C-10-updating-parts.svg │ ├── C-11-updating-parts.svg │ ├── C-12-updating-parts.svg │ ├── C-13-updating-parts.svg │ ├── C-14-updating-parts.svg │ ├── C-8-updating-parts.svg │ └── C-9-updating-parts.svg ├── languages ├── chinese │ └── book │ │ ├── Intro.md │ │ ├── Part-0.md │ │ ├── Part-1.md │ │ ├── Part-10.md │ │ ├── Part-11.md │ │ ├── Part-12.md │ │ ├── Part-13.md │ │ ├── Part-14.md │ │ ├── Part-2.md │ │ ├── Part-3.md │ │ ├── Part-4.md │ │ ├── Part-5.md │ │ ├── Part-6.md │ │ ├── Part-7.md │ │ ├── Part-8.md │ │ ├── Part-9.md │ │ └── README.md └── korean │ └── book │ ├── Intro.md │ ├── Part-0.md │ ├── Part-1.md │ ├── Part-10.md │ ├── Part-11.md │ ├── Part-12.md │ ├── Part-13.md │ ├── Part-14.md │ ├── Part-2.md │ ├── Part-3.md │ ├── Part-4.md │ ├── Part-5.md │ ├── Part-6.md │ ├── Part-7.md │ ├── Part-8.md │ ├── Part-9.md │ └── README.md └── presentation ├── css └── main.css ├── index.html ├── js └── app.js ├── lib ├── anime.min.js ├── code-style │ ├── index.html │ ├── prism.css │ └── prism.js └── impress.js └── steps.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Bohdan Liashenko 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Under the hood: React 2 | This repository contains an explanation of inner work of React. In fact, I was debugging through the entire code base and put all the logic on visual block-schemes, analyzed them, summarized and explained main concepts and approaches. I've already finished with Stack version and now I work with the next, Fiber version. 3 | 4 | 5 | ### I wanted to automate process of "learning and documenting" a complex codebase as much as possible, so I started [Codecrumbs project](https://codecrumbs.io/). It will help to build projects like "Under the hood ReactJs" in a shorter time and in a simpler way! 6 | 7 | 8 | 9 | Each scheme is clickable and can be opened in a new tab, use that to zoom it and be able to read from it. Keep the article and a scheme you are reading about at that moment in separate windows (tabs), that will help to match text and code flow easier. 10 | 11 | We are gonna talk here about both React versions, current one with Stack reconciler and the next one with Fiber (as you probably know, the next version of React will be released soon), so, you can understand better how current React works and appreciate huge achievements on React-Fiber. We use [React v15.4.2](https://github.com/facebook/react/tree/v15.4.2) for explaining how ‘legacy React’ works and React v16.*.*** for ‘Fiber’. Let’s start from old (I have fun to say that) stack version. 12 | 13 | 14 | ## Stack reconciler 15 | [![](./stack/images/intro/all-page-stack-reconciler-25-scale.jpg)](./stack/images/intro/all-page-stack-reconciler.svg) 16 | 17 | The entire scheme is divided into 15 parts, let's get started. 18 | 19 | > Read in the best format from [github-pages website](https://bogdan-lyashenko.github.io/Under-the-hood-ReactJS/). 20 | 21 | * [Intro](./stack/book/Intro.md) 22 | * [Part 0](./stack/book/Part-0.md) 23 | * [Part 1](./stack/book/Part-1.md) 24 | * [Part 2](./stack/book/Part-2.md) 25 | * [Part 3](./stack/book/Part-3.md) 26 | * [Part 4](./stack/book/Part-4.md) 27 | * [Part 5](./stack/book/Part-5.md) 28 | * [Part 6](./stack/book/Part-6.md) 29 | * [Part 7](./stack/book/Part-7.md) 30 | * [Part 8](./stack/book/Part-8.md) 31 | * [Part 9](./stack/book/Part-9.md) 32 | * [Part 10](./stack/book/Part-10.md) 33 | * [Part 11](./stack/book/Part-11.md) 34 | * [Part 12](./stack/book/Part-12.md) 35 | * [Part 13](./stack/book/Part-13.md) 36 | * [Part 14](./stack/book/Part-14.md) 37 | 38 | 39 | 40 | ## Fiber 41 | Will be done with a help of [js-code-to-svg-flowchart tool](https://github.com/Bogdan-Lyashenko/js-code-to-svg-flowchart) later. 42 | 1. [Intro](./fiber/book/Intro.md) [TODO] 43 | 44 | 45 | 46 | ## Languages 47 | - [Chinese](./stack/languages/chinese/book/Intro.md) 48 | - [Korean](./stack/languages/korean/book/Intro.md) 49 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /fiber/book/Intro.md: -------------------------------------------------------------------------------- 1 | #Fiber.. 2 | Still in progress.. 3 | I work on big scheme right now.. 4 | -------------------------------------------------------------------------------- /stack/book/Part-10.md: -------------------------------------------------------------------------------- 1 | ## Part 10 2 | 3 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/10/part-10.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/10/part-10.svg) 4 | 5 | 10.0 Part 10 (clickable) 6 | 7 | ### Dirty components 8 | 9 | As you can see, React loop through `dirtyComponents`(1), and call `ReactUpdates.runBatchedUpdates`(2), through transaction! Transaction? The new one, but why? Let’s see. 10 | 11 | The transaction type is `ReactUpdatesFlushTransaction` and, we’ve already mentioned that before, we need to check `wrappers` to understand what the transaction actually does. A small hint from the code comment: 12 | > ‘ReactUpdatesFlushTransaction's wrappers will clear the dirtyComponents array and perform any updates enqueued by mount-ready handlers (i.e., componentDidUpdate)’ 13 | 14 | But, anyway, we need to prove that. There are two wrappers `NESTED_UPDATES` and `UPDATE_QUEUEING`. On `initialize` phase we store `dirtyComponentsLength` (3) and, as you can check on `close`, React compares, maybe during updates a flush number of dirty components was changed, so, obviously it’s needed to run `flushBatchedUpdates` one more time. You see, no magic, everything is pretty straightforward. 15 | 16 | Well.. one magic moment actually is present. `ReactUpdatesFlushTransaction` overrides `Transaction.perform` method, because… it actually requires behavior from `ReactReconcileTransaction` (transaction is used during mounting and allows to keep app state safe). So, inside `ReactUpdatesFlushTransaction.perform` method, `ReactReconcileTransaction` is used as well, so transaction method actually is wrapped one more time. 17 | 18 | So, technically, it looks like: 19 | 20 | ```javascript 21 | [NESTED_UPDATES, UPDATE_QUEUEING].initialize() 22 | [SELECTION_RESTORATION, EVENT_SUPPRESSION, ON_DOM_READY_QUEUEING].initialize() 23 | 24 | method -> ReactUpdates.runBatchedUpdates 25 | 26 | [SELECTION_RESTORATION, EVENT_SUPPRESSION, ON_DOM_READY_QUEUEING].close() 27 | [NESTED_UPDATES, UPDATE_QUEUEING].close() 28 | ``` 29 | 30 | We will go back to the transaction in the end, to double check how it helps to finish method work, but now, let’s see details of `ReactUpdates.runBatchedUpdates`(2) (`\src\renderers\shared\stack\reconciler\ReactUpdates.js#125`) 31 | 32 | The first thing we should do from the very beginning - sort `dirtyComponets` array (4). How to sort? By `mount order` (integer number was set to a component when instance mounted), it means that parents (they were mounted first) will be updated first, children next, and so on. 33 | The next step, we increase `updateBatchNumber`, it’s something like ID for current reconciling. According to comment in the code: 34 | > ‘Any updates enqueued while reconciling must be performed after this entire batch. Otherwise, if dirtyComponents is [A, B] where A has children B and C, B could update twice in a single batch if C's render enqueues an update to B (since B would have already updated, we should skip it, and the only way we can know to do so is by checking the batch counter).’ 35 | 36 | It helps actually to avoid double updates for the same components. 37 | 38 | Well done, finally we loop through `dirtyComponents` and pass each component to `ReactReconciler.performUpdateIfNecessary` (5), where actually `performUpdateIfNecessary` method will be called from `ReactCompositeComponent` instance, so, move on to `ReactCompositeComponent` code again and its method `updateComponent`. Here we can find something interesting for us, so, let’s dive deeper. 39 | 40 | ### Alright, we’ve finished *Part 10*. 41 | 42 | Let’s recap how we got here. Let's look at the scheme one more time, then remove redundant less important pieces, and it becomes this: 43 | 44 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/10/part-10-A.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/10/part-10-A.svg) 45 | 46 | 10.1 Part 10 simplified (clickable) 47 | 48 | And we should probably fix spaces and alignment as well: 49 | 50 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/10/part-10-B.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/10/part-10-B.svg) 51 | 52 | 10.2 Part 10 simplified & refactored (clickable) 53 | 54 | Nice. In fact, that’s all that happens here. So, we can take the essential value from *Part 10* and use it for the final `updating` scheme: 55 | 56 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/10/part-10-C.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/10/part-10-C.svg) 57 | 58 | 10.3 Part 10 essential value (clickable) 59 | 60 | And then we're done! 61 | 62 | 63 | [To the next page: Part 11 >>](./Part-11.md) 64 | 65 | [<< To the previous page: Part 9](./Part-9.md) 66 | 67 | 68 | [Home](../../README.md) 69 | -------------------------------------------------------------------------------- /stack/book/Part-11.md: -------------------------------------------------------------------------------- 1 | ## Part 11 2 | 3 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/11/part-11.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/11/part-11.svg) 4 | 5 | 11.0 Part 11 (clickable) 6 | 7 | ### Update component 8 | 9 | Comment in the code which describes the method says: 10 | >‘Perform an update to a mounted component. The componentWillReceiveProps and shouldComponentUpdate methods are called, then (assuming the update isn't skipped) the remaining update lifecycle methods are called and the DOM representation is updated. By default, this implements React's rendering and reconciliation algorithm. Sophisticated clients may wish to override this.’ 11 | 12 | Alright… sounds reasonable. 13 | 14 | The first thing we check if `props` (1) were changed, technically, the method `updateComponent` can be called in two different scenarios if `setState` was called or `props` were changed. If `props` were actually changed, then life-cycle method `componentWillReceiveProps` will be called. After, React re-calculate `nextState` (2) based on `pending state queue` (queue of partial state objects which we set before, in our case queue will be like [{message: "click state message"}]). Of course, in the case with just `props` update state will be untouched. 15 | 16 | Well, next step, we set `shouldUpdate` to default value `true`(3). That’s actually why when `shouldComponentUpdate` is not specified, a component is updated by default. Then, check if it’s not `force update`. As you know, it’s possible to call `forceUpdate` from component to update it, instead of changing `state` or `props`, but, according to React official docs, using this method is bad practice. So, in a case of force update component will be updated permanently, otherwise, specified from the component method `shouldComponentUpdate` will be called, and `shouldUpdate` will be re-assigned with its result value. If it's determined that a component should not update, React still needs to set `props` and `state` but shortcut the rest of the update. 17 | 18 | ### Alright, we’ve finished *Part 11*. 19 | 20 | Let’s recap how we got here. Let's look at the scheme one more time, then remove redundant less important pieces, and it becomes this: 21 | 22 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/11/part-11-A.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/11/part-11-A.svg) 23 | 24 | 11.1 Part 11 simplified (clickable) 25 | 26 | And we should probably fix spaces and alignment as well: 27 | 28 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/11/part-11-B.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/11/part-11-B.svg) 29 | 30 | 11.2 Part 11 simplified & refactored (clickable) 31 | 32 | Nice. In fact, that’s all that happens here. So, we can take the essential value from *Part 11* and use it for the final `updating` scheme: 33 | 34 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/11/part-11-C.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/11/part-11-C.svg) 35 | 36 | 11.3 Part 11 essential value (clickable) 37 | 38 | And then we're done! 39 | 40 | 41 | [To the next page: Part 12 >>](./Part-12.md) 42 | 43 | [<< To the previous page: Part 10](./Part-10.md) 44 | 45 | 46 | [Home](../../README.md) 47 | -------------------------------------------------------------------------------- /stack/book/Part-12.md: -------------------------------------------------------------------------------- 1 | ## Part 12 2 | 3 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/12/part-12.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/12/part-12.svg) 4 | 5 | 12.0 Part 12 (clickable) 6 | 7 | ### If components actually should update.. 8 | 9 | So, it’s the very beginning of the update, it means it’s a good place to call `componentWillUpdate` hook if it’s specified (1). Then, re-render component and enqueue the call of one more well-known method `componentDidUpdate` (postpone the call, because it should be called in the very end of the update). 10 | What about re-render? Actually, what we need to do here it’s to call the component's `render` method and update the DOM accordingly. So, the first step, we call `render`(2) method from our instance (`ExampleApplication`) and store the result of render (React elements which were returned from a method call). Then, we compare it previous rendered element and see, if DOM actually should be updated. 11 | 12 | You see this, right, it’s actually one of React’s killer features, it avoids redundant DOM updates, what makes React performance really good. 13 | Due to the code comment `shouldUpdateReactComponent`(3) method: 14 | > ‘determines if the existing instance should be updated as opposed to being destroyed or replaced by a new instance’. 15 | 16 | So, roughly speaking, the method check if element should be replaced completely, it means, old one should be `unmounted` first, then new element (got from `render`) should be mounted and markup, received from the `mount` method, should be placed instead of current element, or, if element can be partially updated. The major reason to replace element completely is a case when a new element is empty (was removed by `render` logic) or its type is different, e.g. it was `div` but now it’s something else. Let’s see the code, it’s simple enough. 17 | 18 | ```javascript 19 | ///src/renderers/shared/shared/shouldUpdateReactComponent.js#25 20 | 21 | function shouldUpdateReactComponent(prevElement, nextElement) { 22 | var prevEmpty = prevElement === null || prevElement === false; 23 | var nextEmpty = nextElement === null || nextElement === false; 24 | if (prevEmpty || nextEmpty) { 25 | return prevEmpty === nextEmpty; 26 | } 27 | 28 | var prevType = typeof prevElement; 29 | var nextType = typeof nextElement; 30 | if (prevType === 'string' || prevType === 'number') { 31 | return (nextType === 'string' || nextType === 'number'); 32 | } else { 33 | return ( 34 | nextType === 'object' && 35 | prevElement.type === nextElement.type && 36 | prevElement.key === nextElement.key 37 | ); 38 | } 39 | } 40 | ``` 41 | 42 | Alright, in the case with our `ExampleApplication` we just updated `state` property which doesn’t affect `render` so much, so, we go with the second scenario, meaning `update`. 43 | 44 | ### Alright, we’ve finished *Part 12*. 45 | 46 | Let’s recap how we got here. Let's look at the scheme one more time, then remove redundant less important pieces, and it becomes this: 47 | 48 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/12/part-12-A.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/12/part-12-A.svg) 49 | 50 | 12.1 Part 12 simplified (clickable) 51 | 52 | And we should probably fix spaces and alignment as well: 53 | 54 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/12/part-12-B.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/12/part-12-B.svg) 55 | 56 | 12.2 Part 12 simplified & refactored (clickable) 57 | 58 | Nice. In fact, that’s all that happens here. So, we can take the essential value from *Part 12* and use it for the final `updating` scheme: 59 | 60 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/12/part-12-C.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/12/part-12-C.svg) 61 | 62 | 12.3 Part 12 essential value (clickable) 63 | 64 | And then we're done! 65 | 66 | 67 | [To the next page: Part 13 >>](./Part-13.md) 68 | 69 | [<< To the previous page: Part 11](./Part-11.md) 70 | 71 | 72 | [Home](../../README.md) 73 | -------------------------------------------------------------------------------- /stack/book/Part-13.md: -------------------------------------------------------------------------------- 1 | ## Part 13 2 | 3 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/13/part-13.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/13/part-13.svg) 4 | 5 | 13.0 Part 13 (clickable) 6 | 7 | ### Receive component (next element, to be more precise) 8 | 9 | Well, through `ReactReconciler.receiveComponent` React actually calls `receiveComponent` from `ReactDOMComponent` and pass next element there. Reassign it on DOM component instance and call update method. `updateComponent` method actually performs two main actions: update DOM properties and DOM children, based on `prev` and `next` props. Good for us, we already analyzed `_updateDOMProperties` (`src\renderers\dom\shared\ReactDOMComponent.js#946`) method. As you remember, this method mostly process HTML elements properties and attributes, compute styles, handle event listeners etc. What is left, it’s `_updateDOMChildren` (`src\renderers\dom\shared\ReactDOMComponent.js#1076`). 10 | 11 | ### Alright, we’ve finished *Part 13*. That was a short one.) 12 | 13 | Let’s recap how we got here. Let's look at the scheme one more time, then remove redundant less important pieces, and it becomes this: 14 | 15 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/13/part-13-A.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/13/part-13-A.svg) 16 | 17 | 13.1 Part 13 simplified (clickable) 18 | 19 | And we should probably fix spaces and alignment as well: 20 | 21 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/13/part-13-B.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/13/part-13-B.svg) 22 | 23 | 13.2 Part 13 simplified & refactored (clickable) 24 | 25 | Nice. In fact, that’s all that happens here. So, we can take the essential value from *Part 13* and use it for the final `updating` scheme: 26 | 27 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/13/part-13-C.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/13/part-13-C.svg) 28 | 29 | 13.3 Part 13 essential value (clickable) 30 | 31 | And then we're done! 32 | 33 | 34 | [To the next page: Part 14 >>](./Part-14.md) 35 | 36 | [<< To the previous page: Part 12](./Part-12.md) 37 | 38 | 39 | [Home](../../README.md) 40 | -------------------------------------------------------------------------------- /stack/book/Part-2.md: -------------------------------------------------------------------------------- 1 | ## Part 2 2 | 3 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/2/part-2.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/2/part-2.svg) 4 | 5 | 2.0 Part 2 (clickable) 6 | 7 | ### One more transaction 8 | 9 | This time it’s `ReactReconcileTransaction`. As you already know, the major thing that is interesting to us is transaction wrappers. There are three wrappers: 10 | 11 | ```javascript 12 | //\src\renderers\dom\client\ReactReconcileTransaction.js#89 13 | var TRANSACTION_WRAPPERS = [ 14 | SELECTION_RESTORATION, 15 | EVENT_SUPPRESSION, 16 | ON_DOM_READY_QUEUEING, 17 | ]; 18 | ``` 19 | 20 | As we can see these wrappers are used mostly to **keep the actual state**, lock some changeable values before method calls, and release them after. So, React ensures that, for example, the selection range (currently selected text input) is not disturbed by performing the transaction (get selected on `initialize` and restore on `close`). Also, it suppresses events (blur/focus) that could be inadvertently dispatched due to high-level DOM manipulations (like temporarily removing a text input from the DOM) so it **disables `ReactBrowserEventEmitter`** on `initialize` and enables on `close`. 21 | 22 | Well, we are really close to starting the component mount, which will return us markup ready to put into DOM. Actually, `ReactReconciler.mountComponent` is just wrapper, or, it's more correct to say ‘mediator’. It delegates method mounting to component modules. This is an important moment, so let’s highlight: 23 | 24 | > `ReactReconciler` module is always called in cases when implementation of some logic **depends on platform**, like this exact case. Mount is different per platform, so the ‘main module’ talks to `ReactReconciler` and `ReactReconciler` knows what to do next. 25 | 26 | Alright, let's move on to the component’s method `mountComponent`. It's probably the method you have already heard about. It initializes the component, renders markup, and registers event listeners. You see, a long way through and we finally see a component mounting call. After calling mount, we should get actual HTML elements which can be put into the document. 27 | 28 | 29 | ### Alright, we’ve finished *Part 2*. 30 | 31 | Let’s recap how we got here. Let's look at the scheme one more time, then remove redundant less important pieces, and it becomes this: 32 | 33 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/2/part-2-A.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/2/part-2-A.svg) 34 | 35 | 2.1 Part 2 simplified (clickable) 36 | 37 | And we should probably fix spaces and alignment as well: 38 | 39 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/2/part-2-B.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/2/part-2-B.svg) 40 | 41 | 2.2 Part 2 simplified & refactored (clickable) 42 | 43 | Nice. In fact, that’s all that happens here. So, we can take the essential value from *Part 1* and use it for the final `mounting` scheme: 44 | 45 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/2/part-2-C.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/2/part-2-C.svg) 46 | 47 | 2.3 Part 2 essential value (clickable) 48 | 49 | And then we're done! 50 | 51 | 52 | [To the next page: Part 3 >>](./Part-3.md) 53 | 54 | [<< To the previous page: Part 1](./Part-1.md) 55 | 56 | 57 | [Home](../../README.md) 58 | -------------------------------------------------------------------------------- /stack/book/Part-4.md: -------------------------------------------------------------------------------- 1 | ## Part 4 2 | 3 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/4/part-4.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/4/part-4.svg) 4 | 5 | 4.0 Part 4 (clickable) 6 | 7 | ### Child mounting 8 | 9 | Going crazy, right? Let’s continue with investigating the `mount` method. 10 | 11 | So, if `_tag` contains a ‘complex’ tag (1), like video, form, textarea, etc., it will require additional wrapping. It adds more event listeners for each media event, like ‘volumechange’ for `audio` tags, or it just wraps native behavior of tags like `select`, `textarea`, etc. 12 | There are a bunch of wrappers for elements like that, such as `ReactDOMSelect` and `ReactDOMTextarea` (inside src\renderers\dom\client\wrappers\ folder). In our case it’s just simply `div`, no additional processing there. 13 | 14 | ### Props validation 15 | 16 | The next validation method is called just to make sure that the internal `props` are set correctly, otherwise it will throw errors. For example, if `props.dangerouslySetInnerHTML` is set (usually we do that when try to insert HTML from a string) and object key `__html` is missed, the next error will be thrown: 17 | 18 | > `props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. Please visit https://fb.me/react-invariant-dangerously-set-inner-html for more information. 19 | 20 | ### Create HTML element 21 | 22 | Then, the actual HTML element will be created (3) by `document.createElement`, which will instantiate the real HTML `div` for us. Before we worked only with virtual representation and now, you can see it for the first time. 23 | 24 | 25 | ### Alright, we’ve finished *Part 4*. 26 | 27 | Let’s recap how we got here. Let's look at the scheme one more time, then remove redundant less important pieces, and it becomes this: 28 | 29 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/4/part-4-A.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/4/part-4-A.svg) 30 | 31 | 4.1 Part 4 simplified (clickable) 32 | 33 | And we should probably fix spaces and alignment as well: 34 | 35 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/4/part-4-B.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/4/part-4-B.svg) 36 | 37 | 4.2 Part 4 simplified & refactored (clickable) 38 | 39 | Nice. In fact, that’s all that happens here. So, we can take the essential value from *Part 4* and use it for the final `mounting` scheme: 40 | 41 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/4/part-4-C.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/4/part-4-C.svg) 42 | 43 | 4.3 Part 4 essential value (clickable) 44 | 45 | And then we're done! 46 | 47 | 48 | [To the next page: Part 5 >>](./Part-5.md) 49 | 50 | [<< To the previous page: Part 3](./Part-3.md) 51 | 52 | 53 | [Home](../../README.md) 54 | -------------------------------------------------------------------------------- /stack/book/Part-5.md: -------------------------------------------------------------------------------- 1 | ## Part 5 2 | 3 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/5/part-5.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/5/part-5.svg) 4 | 5 | 5.0 Part 5 (clickable) 6 | 7 | ### Update DOM properties 8 | 9 | Alright, that looks scary, right? The main idea is to apply the diff of previous and new `props` efficiently. Look at the method comment in the code: 10 | > “Reconciles the properties by detecting differences in property values and updating the DOM as necessary. This function is probably the single most critical path for performance optimization.” 11 | 12 | There are two loops actually. First, through previous `props` and then, through next `props`. In our case, with mounting, `lastProps` (previous) is empty (obviously, it’s the first time when we assign props), but still, let see what’s going on here. 13 | 14 | ### Last `props` loop 15 | In the first step, we check if `nextProps` contains the same prop value. If so, we just skip it, because it will be handled later in the `nextProps` loop. Then, we reset style values, delete event listeners (if they were set before), and remove DOM attribute and DOM properties values. For attributes, we make sure they are not one of the `RESERVED_PROPS`, that it's actually `prop`, like `children` or `dangerouslySetInnerHTML`. 16 | 17 | ### Next `props` loop 18 | Here, the first step is to check if `prop` was changed, meaning if the next value is different than the old one. If not, we don’t do anything. For `styles`, (you might have noticed it’s treated a bit special) we update values that have changed since `lastProp`. Then, we add the events listeners (yes, exactly the ones like `onClick`, etc). Let’s analyze that with more details. 19 | 20 | The important thing is, across the React app, all work is passed through named ‘synthetic’ events. Nothing is special, it's just a few more wrappers for more efficient work. Next thing, the mediator module for managing event listeners is `EventPluginHub` (`src\renderers\shared\stack\event\EventPluginHub.js`). It contains a `listenerBank` map for caching and managing all listeners. 21 | We are going to add our event listeners, but not right away. The point is, that we should add listeners when the component and DOM element is ready for handling events. Seems like we have delayed execution here, but you will probably ask, how can we know when that moment happens? Well, it’s time for the next answer! Do you remember when we passed `transaction` through all of the methods and calls? Exactly! We did that because it can be helpful exactly for such a situation. Let’s see the proof in the code: 22 | 23 | ```javascript 24 | //src\renderers\dom\shared\ReactDOMComponent.js#222 25 | transaction.getReactMountReady().enqueue(putListener, { 26 | inst: inst, 27 | registrationName: registrationName, 28 | listener: listener, 29 | }); 30 | ``` 31 | 32 | Okay, after the event listeners, we set DOM attribute and DOM property values. Same as before, for attributes we make sure they are not one of the `RESERVED_PROPS`, that it’s actually `prop`, like `children` or `dangerouslySetInnerHTML`. 33 | 34 | During the processing of the last and next props, we computed the `styleUpdates` config and now pass it to the `CSSPropertyOperations` module. 35 | 36 | Well, we’ve finished updating the properties. Let’s move on. 37 | 38 | ### Alright, we’ve finished *Part 5*. 39 | 40 | Let’s recap how we got here. Let's look at the scheme one more time, then remove redundant less important pieces, and it becomes this: 41 | 42 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/5/part-5-A.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/5/part-5-A.svg) 43 | 44 | 5.1 Part 5 simplified (clickable) 45 | 46 | And we should probably fix spaces and alignment as well: 47 | 48 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/5/part-5-B.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/5/part-5-B.svg) 49 | 50 | 5.2 Part 5 simplified & refactored (clickable) 51 | 52 | Nice. In fact, that’s all that happens here. So, we can take the essential value from *Part 5* and use it for the final `mounting` scheme: 53 | 54 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/5/part-5-C.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/5/part-5-C.svg) 55 | 56 | 5.3 Part 5 essential value (clickable) 57 | 58 | And then we're done! 59 | 60 | 61 | [To the next page: Part 6 >>](./Part-6.md) 62 | 63 | [<< To the previous page: Part 4](./Part-4.md) 64 | 65 | 66 | [Home](../../README.md) 67 | -------------------------------------------------------------------------------- /stack/book/Part-6.md: -------------------------------------------------------------------------------- 1 | ## Part 6 2 | 3 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/6/part-6.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/6/part-6.svg) 4 | 5 | 6.0 Part 6 (clickable) 6 | 7 | ### Create initial children 8 | 9 | Seems like the element itself is finished, so now we can continue with its children. Two steps here: children should be mounted (`this.mountChildren`)(1) and connected to the parent (`DOMLazyTree.queueChild`)(2). Let’s move to children mounting because it’s obviously more interesting. 10 | 11 | There is a separate module called `ReactMultiChild` (`src\renderers\shared\stack\reconciler\ReactMultiChild.js`) to manage children. Nice, let’s check the `mountChildren` method then. It contains two main tasks as well. First of all, we instantiate children (use `ReactChildReconciler` for that) and mount them. What children are actually here? It can be a simple HTML tag or another custom component. To handle HTML we need to instantiate `ReactDOMComponent` and for custom component - `ReactCompositeComponent`. The mounting flow, again, depends on what the child type is. 12 | 13 | ### One more time 14 | 15 | If you are still reading this, it's probably time to clarify and review the overall process one more time. Let’s take a break and recollect the sequence of objects. 16 | 17 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/6/overall-mounting-scheme.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/6/overall-mounting-scheme.svg) 18 | 19 | 6.1 Overall mounting scheme (clickable) 20 | 21 | 1) React instantiates `ReactCompositeComponent` for each of your custom components (with component lifecycle hooks like `componentWillMount`, etc) and mounts it. 22 | 23 | 2) During mounting, at first, an instance of your custom component will be created (`constructor` called). 24 | 25 | 3) Then, its render method is called (for a simple example, render returns `div`) and `React.createElement` creates the React elements. It can be called directly or after parsing JSX by Babel and replacing tags in your render. But, it’s not exactly what we need, see what's next below. 26 | 27 | 4) We need a DOM component for our `div`. So, during an instantiation process, we create instances of `ReactDOMComponent` from the element-objects (mentioned above). 28 | 29 | 5) Then, we need to mount the DOM component. That actually means we create the DOM elements and assign event listeners, etc. 30 | 31 | 6) Then, we process the initial children of our DOM component. We create instances of them and mount them as well. Depending on what each item of the children is, a custom component or just an HTML tag, we recurse to step 1) or step 5) respectively. And then again for all nested elements. 32 | 33 | That’s it. It's pretty straightforward as you can see. 34 | 35 | So, mounting is basically finished. Enqueue the `componentDidMount` method! Great job. 36 | 37 | ### Alright, we’ve finished *Part 6*. 38 | 39 | Let’s recap how we got here. Let's look at the scheme one more time, then remove redundant less important pieces, and it becomes this: 40 | 41 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/6/part-6-A.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/6/part-6-A.svg) 42 | 43 | 6.2 Part 6 simplified (clickable) 44 | 45 | And we should probably fix spaces and alignment as well: 46 | 47 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/6/part-6-B.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/6/part-6-B.svg) 48 | 49 | 6.3 Part 6 simplified & refactored (clickable) 50 | 51 | Nice. In fact, that’s all that happens here. So, we can take the essential value from *Part 6* and use it for the final `mounting` scheme: 52 | 53 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/6/part-6-C.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/6/part-6-C.svg) 54 | 55 | 6.4 Part 6 essential value (clickable) 56 | 57 | And then we're done! 58 | 59 | 60 | [To the next page: Part 7 >>](./Part-7.md) 61 | 62 | [<< To the previous page: Part 5](./Part-5.md) 63 | 64 | 65 | [Home](../../README.md) 66 | -------------------------------------------------------------------------------- /stack/book/Part-7.md: -------------------------------------------------------------------------------- 1 | ## Part 7 2 | 3 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/7/part-7.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/7/part-7.svg) 4 | 5 | 7.0 Part 7 (clickable) 6 | 7 | ### Back to the beginning 8 | 9 | After mounting as result of method execution, we have HTML elements which are ready to be set into a document. Actually, `markup` (1) is generated, but `mountComponent`, despite how it’s named, is not actually HTML markup. It’s a data structure with fields `children`, `node` (actual DOM nodes), etc. But, we have our HTML element to put into the container (the one specified as the container in the `ReactDOM.render` call). While adding it into DOM, React will erase everything that was there before. `DOMLazyTree`(2) is a utils class that performs some operations with tree data structures, which we're actually doing during work with the DOM. 10 | 11 | The last thing is `parentNode.insertBefore(tree.node)`(3), where `parentNode` is the container `div` node and `tree.node` is actually our `ExampleAppliication` div node. Nice, the HTML elements that were created during mounting were finally inserted into the document. 12 | 13 | So, that’s it? Not exactly. As you remember, the `mount` call was wrapped into a transaction. It means that we should close it. Let’s check our `close` wrappers list. Mostly, we should restore some locked behavior `ReactInputSelection.restoreSelection()`, `ReactBrowserEventEmitter.setEnabled(previouslyEnabled)`, but also, we will notify all of the callbacks `this.reactMountReady.notifyAll`(4) we put into `transaction.reactMountReady` queue before. One of them is our favorite `componentDidMount`, which will be triggered exactly by the `close` wrapper. 14 | 15 | Now you have a clear picture of what ‘component did mount’ actually means. Cheers! 16 | 17 | ### One more transaction to close 18 | 19 | Well, actually, that transaction was not only one. We forgot one more which was used to wrap the `ReactMount.batchedMountComponentIntoNode` call. Let’s close it as well. 20 | 21 | Here, we check the wrapper `ReactUpdates.flushBatchedUpdates`(5), which will process `dirtyComponents`. Sounds interesting, ya? Well, it's good or bad news. We just did our first mount, so there are no dirty components yet. It means that it’s an idle call. So, we can close this transaction as well and say that the batching strategy updates are done. 22 | 23 | ### Alright, we’ve finished *Part 7*. 24 | 25 | Let’s recap how we got here. Let's look at the scheme one more time, then remove redundant less important pieces, and it becomes this: 26 | 27 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/7/part-7-A.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/7/part-7-A.svg) 28 | 29 | 7.1 Part 7 simplified (clickable) 30 | 31 | And we should probably fix spaces and alignment as well: 32 | 33 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/7/part-7-B.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/7/part-7-B.svg) 34 | 35 | 7.2 Part 7 simplified & refactored (clickable) 36 | 37 | Nice. In fact, that’s all that happens here. So, we can take the essential value from *Part 7* and use it for the final `mounting` scheme: 38 | 39 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/7/part-7-C.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/7/part-7-C.svg) 40 | 41 | 7.3 Part 7 essential value (clickable) 42 | 43 | And then we're done! In fact, we're done with mounting. Let's see it below! 44 | 45 | 46 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/7/mounting-parts-C.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/7/mounting-parts-C.svg) 47 | 48 | 7.4 Mounting (clickable) 49 | 50 | [To the next page: Part 8 >>](./Part-8.md) 51 | 52 | [<< To the previous page: Part 6](./Part-6.md) 53 | 54 | 55 | [Home](../../README.md) 56 | -------------------------------------------------------------------------------- /stack/book/Part-8.md: -------------------------------------------------------------------------------- 1 | ## Part 8 2 | 3 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/8/part-8.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/8/part-8.svg) 4 | 5 | 8.0 Part 8 (clickable) 6 | 7 | ### `this.setState` 8 | 9 | We know how mounting works, but now, let’s go from the another side. Yes, `setState` method, one more piece of cake! 10 | 11 | First of all, why we actually can call some method called `setState`? Well, that’s clear enough, we inherited our component from `ReactComponent`. Alright, then, it’s easy to find this class in React source and check its `setState` method. 12 | 13 | ```javascript 14 | //src\isomorphic\modern\class\ReactComponent.js#68 15 | this.updater.enqueueSetState(this, partialState) 16 | ``` 17 | As you can see, there is some `updater` interface. What that `updater` is? Well, if you check mounting process we’ve just analyzed, during `mountComponent`, instance receives `updater` property as a reference to `ReactUpdateQueue` (`src\renderers\shared\stack\reconciler\ReactUpdateQueue.js`). 18 | 19 | Well, dive inside `enqueueSetState` (1) method and see that, at first, it pushes partial state (a partial state is an object you pass into `this.setState`) to `_pendingStateQueue` (2) of internal instance (just to remind: public instance, it’s actually our custom component `ExampleApplication` and, internal instance is `ReactCompositeComponent` which was created during mounting), secondary, we `enqueueUpdate`, what actually check if updates already in progress and push our component to `dirtyComponents` list, otherwise, if not - init update transaction and then push component to `dirtyComponents` list. 20 | 21 | To summarize this, each component has own list of pending states, means, each time you call `setState` in one transaction, you just push that objects into a queue, then, later, they will be merged into component state one by one. And, when you call `setState`, you add your component into `dirtyComponents` list. Probably, you are already wondering, how that `dirtyComponents` are processed? You are right, that’s next important piece of the puzzle... 22 | 23 | ### Alright, we’ve finished *Part 8*. 24 | 25 | Let’s recap how we got here. Let's look at the scheme one more time, then remove redundant less important pieces, and it becomes this: 26 | 27 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/8/part-8-A.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/8/part-8-A.svg) 28 | 29 | 8.1 Part 8 simplified (clickable) 30 | 31 | And we should probably fix spaces and alignment as well: 32 | 33 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/8/part-8-B.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/8/part-8-B.svg) 34 | 35 | 8.2 Part 8 simplified & refactored (clickable) 36 | 37 | Nice. In fact, that’s all that happens here. So, we can take the essential value from *Part 8* and use it for the final `updating` scheme: 38 | 39 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/8/part-8-C.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/8/part-8-C.svg) 40 | 41 | 8.3 Part 8 essential value (clickable) 42 | 43 | And then we're done! 44 | 45 | 46 | [To the next page: Part 9 >>](./Part-9.md) 47 | 48 | [<< To the previous page: Part 7](./Part-7.md) 49 | 50 | 51 | [Home](../../README.md) 52 | -------------------------------------------------------------------------------- /stack/book/Part-9.md: -------------------------------------------------------------------------------- 1 | ## Part 9 2 | 3 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/9/part-9.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/9/part-9.svg) 4 | 5 | 9.0 Part 9 (clickable) 6 | 7 | ### But let’s move back.. 8 | 9 | As you noticed on the scheme, the call of `setState` method, can be triggered in several ways, be more precise, with, or without, external impact (means ‘user action’). Let’s take two cases: in the first case, the method call is triggered by mouse click, and second, just call from `setTimeout` in `componentDidMount`. 10 | 11 | What actually makes that difference? Well, as you remember, React process updates in `batches`, it means that list of updates should be somehow collected and, then, `flushed`. The thing is that when mouse event appears, it’s handled on the top level and then, through several layers of wrappers the batched update will be started. By the way, as you can see it happens only if `ReactEventListener` is `enabled` (1), and, if you remember, during a component mounting phase, one of `ReactReconcileTransaction` wrappers actually disables it, and make mounting safe. Smart enough! But, what about `setTimeout` case? It’s also simple, before putting a component into `dirtyComponents` list React will make sure that transaction is started (opened), so then, later, it should be closed and updates flushed. 12 | 13 | As you know, React implements ‘synthetic events’, some ‘syntax sugar’ which in fact wraps native events. But then, later, they still try to behave how we all used to see events. You can see the comment in the code: 14 | > ‘To help development we can get better dev tool integration by simulating a real browser event’ 15 | 16 | ```javascript 17 | var fakeNode = document.createElement('react'); 18 | 19 | ReactErrorUtils.invokeGuardedCallback = function (name, func, a) { 20 | var boundFunc = func.bind(null, a); 21 | var evtType = 'react-' + name; 22 | 23 | fakeNode.addEventListener(evtType, boundFunc, false); 24 | 25 | var evt = document.createEvent('Event'); 26 | evt.initEvent(evtType, false, false); 27 | 28 | fakeNode.dispatchEvent(evt); 29 | fakeNode.removeEventListener(evtType, boundFunc, false); 30 | }; 31 | ``` 32 | Alright, back to our update, let’s see one more time. The approach is: 33 | 34 | 1. call setState 35 | 1. open batching transaction if it’s not opened yet 36 | 1. add affected components to `dirtyComponents` list, 37 | 1. close transaction with calling `ReactUpdates.flushBatchedUpdates`, what actually means ‘process whatever was collected into `dirtyComponents`’. 38 | 39 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/9/set-state-update-start.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/9/set-state-update-start.svg) 40 | 41 | 9.1 `setState` start (clickable) 42 | 43 | ### Alright, we’ve finished *Part 9*. 44 | 45 | Let’s recap how we got here. Let's look at the scheme one more time, then remove redundant less important pieces, and it becomes this: 46 | 47 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/9/part-9-A.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/9/part-9-A.svg) 48 | 49 | 9.2 Part 9 simplified (clickable) 50 | 51 | And we should probably fix spaces and alignment as well: 52 | 53 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/9/part-9-B.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/9/part-9-B.svg) 54 | 55 | 9.3 Part 9 simplified & refactored (clickable) 56 | 57 | Nice. In fact, that’s all that happens here. So, we can take the essential value from *Part 9* and use it for the final `updating` scheme: 58 | 59 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/9/part-9-C.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/9/part-9-C.svg) 60 | 61 | 9.6 Part 9 essential value (clickable) 62 | 63 | And then we're done! 64 | 65 | 66 | [To the next page: Part 10 >>](./Part-10.md) 67 | 68 | [<< To the previous page: Part 8](./Part-8.md) 69 | 70 | 71 | [Home](../../README.md) 72 | -------------------------------------------------------------------------------- /stack/images/0/mounting-scheme-1-small.svg: -------------------------------------------------------------------------------- 1 | 2 |
JSX description
JSX description
HTML for document
HTML for document
-------------------------------------------------------------------------------- /stack/images/0/part-0-C.svg: -------------------------------------------------------------------------------- 1 | 2 |
pass your component 
to ReactDom.render
[Not supported by viewer]
create ReactCompositeComponent instance for root element of your react app
to wrap entire VirtualDOM
create <b>ReactCompositeComponent</b> instance for root element of your react app<br>to wrap entire VirtualDOM
-------------------------------------------------------------------------------- /stack/images/1/part-1-C.svg: -------------------------------------------------------------------------------- 1 | 2 |
start component mounting
<div><div>start component <b>mounting</b></div></div>
open batched update
<div><div>open <b>batched</b> update</div></div>
-------------------------------------------------------------------------------- /stack/images/10/part-10-C.svg: -------------------------------------------------------------------------------- 1 | 2 |
sort dirtyComponents 
due to mount order
[Not supported by viewer]
for each component 
performUpdateIfNecessary
[Not supported by viewer]
if number of dirty components was changed after first update - run procedure again
[Not supported by viewer]
notify about update is done
notify about update is done
-------------------------------------------------------------------------------- /stack/images/11/part-11-C.svg: -------------------------------------------------------------------------------- 1 | 2 |
update component...
update component...
call componentWillReceiveProps
call&nbsp;<span><b>componentWillReceiveProps</b></span>
get result of  shouldComponentUpdate
get result of &nbsp;<span><b>shouldComponentUpdate</b></span>
continue update... (if should)
continue update... (if <b>should</b>)
-------------------------------------------------------------------------------- /stack/images/13/part-13-C.svg: -------------------------------------------------------------------------------- 1 | 2 |
update DOM properties...
update DOM properties...
update DOM children...
update DOM children...
-------------------------------------------------------------------------------- /stack/images/14/part-14-C.svg: -------------------------------------------------------------------------------- 1 | 2 |
check type of chilren
check type of chilren
continue children traversal if still complex type (component)...
continue children traversal if still complex type (component)...
when simple type -compare content
when simple type -compare content
if content was changed - proceed with update due to update operation type (text replace, etc.)
[Not supported by viewer]
-------------------------------------------------------------------------------- /stack/images/14/updating-parts-C.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/49cf5d7c7db43c02ac1ac17469a072bd97327614/stack/images/14/updating-parts-C.jpg -------------------------------------------------------------------------------- /stack/images/2/part-2-C.svg: -------------------------------------------------------------------------------- 1 | 2 |
pre-save UI
(disable browser events handling etc.)
pre-save UI <br>(disable browser events handling etc.)
-------------------------------------------------------------------------------- /stack/images/4/part-4-C.svg: -------------------------------------------------------------------------------- 1 | 2 |
create HTML element
 of tag
create HTML element<div>&nbsp;of tag</div>
update DOM properties..
update DOM properties..
create element children...
create element children...
-------------------------------------------------------------------------------- /stack/images/5/part-5-C.svg: -------------------------------------------------------------------------------- 1 | 2 |
calculate difference
between last and new props
calculate difference <br>between last and new <b>props</b>
remove not actual HTML element attributes, properties, styles, event listeners (based on removed props)
[Not supported by viewer]
set new values for HTML element attributes, properties, styles, event listeners (based on new props)
[Not supported by viewer]
-------------------------------------------------------------------------------- /stack/images/6/part-6-C.svg: -------------------------------------------------------------------------------- 1 | 2 |
mount children...
mount children...
create instance of mirror component for each child 
create instance of mirror component for each child&nbsp;
start each child mounting
start each child mounting
-------------------------------------------------------------------------------- /stack/images/7/mounting-parts-C.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/49cf5d7c7db43c02ac1ac17469a072bd97327614/stack/images/7/mounting-parts-C.jpg -------------------------------------------------------------------------------- /stack/images/8/part-8-C.svg: -------------------------------------------------------------------------------- 1 | 2 |
call this.setState(partialState)
<div><font style="font-size: 16px">call <b>this.setState</b>(partialState)</font></div>
add partial state into state updates queue
add partial state into state updates queue
open updates transaction 
if needed
open updates transaction&nbsp;<div>if needed</div>
push component into dirtyComponents
push component into&nbsp;<b>dirtyComponents</b>
-------------------------------------------------------------------------------- /stack/images/9/part-9-C.svg: -------------------------------------------------------------------------------- 1 | 2 |
handle mouse event on top level (if EventListener enabled)
handle mouse event on top level (if EventListener enabled)
call event listener in components (if registered)
call event listener in components (if registered)
open updates transaction 
if needed
open updates transaction&nbsp;<div>if needed</div>
-------------------------------------------------------------------------------- /stack/images/intro/all-page-stack-reconciler-25-scale.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/49cf5d7c7db43c02ac1ac17469a072bd97327614/stack/images/intro/all-page-stack-reconciler-25-scale.jpg -------------------------------------------------------------------------------- /stack/images/mounting-c-parts/C-0-mounting-parts.svg: -------------------------------------------------------------------------------- 1 | 2 |
pass your component 
to ReactDom.render
[Not supported by viewer]
create ReactCompositeComponent instance for root element of your react app
to wrap entire VirtualDOM
[Not supported by viewer]
-------------------------------------------------------------------------------- /stack/images/mounting-c-parts/C-1-mounting-parts.svg: -------------------------------------------------------------------------------- 1 | 2 |
start component mounting..
<div><div>start component <b>mounting..</b></div></div>
open batched update
<div><div>open <b>batched</b> update</div></div>
-------------------------------------------------------------------------------- /stack/images/mounting-c-parts/C-2-mounting-parts.svg: -------------------------------------------------------------------------------- 1 | 2 |
pre-save UI
(disable browser events handling etc.)
pre-save UI <br>(disable browser events handling etc.)
-------------------------------------------------------------------------------- /stack/images/mounting-c-parts/C-4-mounting-parts.svg: -------------------------------------------------------------------------------- 1 | 2 |
create HTML element
 of tag
create HTML element<div>&nbsp;of tag</div>
update DOM properties..
update DOM properties..
create element children...
create element children...
-------------------------------------------------------------------------------- /stack/images/mounting-c-parts/C-5-mounting-parts.svg: -------------------------------------------------------------------------------- 1 | 2 |
calculate difference
between last and 
new props
[Not supported by viewer]
remove not actual HTML element attributes, properties, styles, event listeners (based on removed props)
[Not supported by viewer]
set new values for HTML element attributes, properties, styles, event listeners (based on new props)
[Not supported by viewer]
-------------------------------------------------------------------------------- /stack/images/updating-c-parts/C-10-updating-parts.svg: -------------------------------------------------------------------------------- 1 | 2 |
sort dirtyComponents 
due to mount order
[Not supported by viewer]
for each component 
performUpdateIfNecessary
[Not supported by viewer]
if number of dirty components was changed after first update - run procedure again
[Not supported by viewer]
notify about update is done
notify about update is done
-------------------------------------------------------------------------------- /stack/images/updating-c-parts/C-13-updating-parts.svg: -------------------------------------------------------------------------------- 1 | 2 |
update DOM properties...
update DOM properties...
update DOM children...
update DOM children...
-------------------------------------------------------------------------------- /stack/images/updating-c-parts/C-14-updating-parts.svg: -------------------------------------------------------------------------------- 1 | 2 |
check type of chilren
check type of chilren
continue children traversal if still complex type (component)...
continue children traversal if still complex type (component)...
when simple type -compare content
when simple type -compare content
if content was changed - proceed with update due to update operation type (text replace, etc.)
[Not supported by viewer]
-------------------------------------------------------------------------------- /stack/images/updating-c-parts/C-9-updating-parts.svg: -------------------------------------------------------------------------------- 1 | 2 |
handle mouse event on top level (if EventListener enabled)
handle mouse event on top level (if EventListener enabled)
call event listener in components (if registered)
call event listener in components (if registered)
open updates transaction 
if needed
open updates transaction&nbsp;<div>if needed</div>
-------------------------------------------------------------------------------- /stack/languages/chinese/book/Intro.md: -------------------------------------------------------------------------------- 1 | ## 介绍 2 | 3 | ### 初识流程图 4 | 5 | 6 | [![](https://github.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/raw/master/stack/images/intro/all-page-stack-reconciler-25-scale.jpg)](https://github.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/raw/master/stack/images/intro/all-page-stack-reconciler-25-scale.svg) 7 | 8 | 图 介绍-0:整体流程 9 | 10 | 你可以先花点时间看下整体的流程。虽然看起来很复杂,但它实际上只描述了两个流程:(组件的)挂载和更新。我跳过了卸载,因为它是一种“反向挂载”,而且删除这部分简化了流程图。另外,**这图并不是100%** 同源代码匹配,而只是描述架构的主要部分。总体来说,它大概是源代码的 60%,而另外的 40% 没有多少视觉价值,为了简单起见,我省略了那部分。 11 | 12 | 乍一看,你可能会注意到流程图中有很多颜色。每个逻辑项(流程图上的形状)都以其父模块的颜色高亮显示。例如,如果是从红色的 `模块 B` 调用 `方法 A`,那 `方法 A` 也是红色的。以下是流程图中模块的图例以及每个文件的路径。 13 | 14 | [![图 介绍-1:模块颜色](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/7c2372e1/stack/images/intro/modules-src-path.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/7c2372e1/stack/images/intro/modules-src-path.svg) 15 | 16 | 17 | 18 | 让我们把它们放在一张流程图中,看看**模块之间的依赖关系**。 19 | 20 | [![图 介绍-2 模块依赖关系](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/7c2372e1/stack/images/intro/files-scheme.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/7c2372e1/stack/images/intro/files-scheme.svg) 21 | 22 | 23 | 24 | 你可能知道,React 是为**支持多种环境**而构建的。 25 | - 移动端(**ReactNative**) 26 | - 浏览器(**ReactDOM**) 27 | - 服务端渲染 28 | - **ReactART**(使用 React 绘制矢量图形) 29 | - 其它 30 | 31 | 因此,一些文件实际上比上面流程图中列出的要更大。以下是包含多环境支持的相同的流程图。 32 | 33 | [![介绍 图-3 多平台模块依赖关系](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/7c2372e1/stack/images/intro/modules-per-platform-scheme.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/7c2372e1/stack/images/intro/modules-per-platform-scheme.svg) 34 | 35 | 36 | 37 | 如你所见,有些项似乎翻倍了。这表明它们对每个平台都有一个独立的实现。让我们来看一些简单例子,例如 ReactEventListener,显然,不同平台会有不同的实现。从技术上讲,你可以想象,这些依赖于平台的模块,应该以某种方式注入或连接到当前的逻辑流程中。实际上有很多这样的注入器,因为它们的用法是标准组合模式的一部分。同样,为了简单起见,我选择忽略它们。 38 | 39 | 让我们来学习下**常规浏览器**中 **React DOM** 的逻辑流程。这是最常用的平台,并完全覆盖了所有 React 的架构设计理念。 40 | 41 | 42 | ### 代码示例 43 | 44 | 学习框架或者库的源码的最佳方式是什么?没错,研读并调试源码。那好,我们将要调试这**两个流程**:**ReactDOM.render** 和 **component.setState** 这两者对应了组件的挂载和更新。让我们来看一下我们能编写一些什么样的代码来开始学习。我们需要什么呢?或许几个具有简单渲染的小组件就可以了,因为更容易调试。 45 | 46 | ```javascript 47 | class ChildCmp extends React.Component { 48 | render() { 49 | return
{this.props.childMessage}
50 | } 51 | } 52 | 53 | class ExampleApplication extends React.Component { 54 | constructor(props) { 55 | super(props); 56 | this.state = {message: 'no message'}; 57 | } 58 | 59 | componentWillMount() { 60 | //... 61 | } 62 | 63 | componentDidMount() { 64 | /* setTimeout(()=> { 65 | this.setState({ message: 'timeout state message' }); 66 | }, 1000); */ 67 | } 68 | 69 | shouldComponentUpdate(nextProps, nextState, nextContext) { 70 | return true; 71 | } 72 | 73 | componentDidUpdate(prevProps, prevState, prevContext) { 74 | //... 75 | } 76 | 77 | componentWillReceiveProps(nextProps) { 78 | //... 79 | } 80 | 81 | componentWillUnmount() { 82 | //... 83 | } 84 | 85 | onClickHandler() { 86 | /* this.setState({ message: 'click state message' }); */ 87 | } 88 | 89 | render() { 90 | return
91 | 92 | 93 | And some text as well! 94 |
95 | } 96 | } 97 | 98 | ReactDOM.render( 99 | , 100 | document.getElementById('container'), 101 | function() {} 102 | ); 103 | ``` 104 | 105 | 我们已经准备好开始学习了。让我们先来分析流程图中的第一部分。一个接一个,我们会将它们全部分析完。 106 | 107 | [下一页:Part 0 >>](./Part-0.md) 108 | 109 | 110 | [首页](./README.md) 111 | -------------------------------------------------------------------------------- /stack/languages/chinese/book/Part-0.md: -------------------------------------------------------------------------------- 1 | ## 第 0 部分 2 | 3 | [![图 0-0](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/part-0.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/part-0.svg) 4 | 5 | 6 | 7 | ### ReactDOM.render 8 | 让我们从 ReactDOM.render 的调用开始。 9 | 10 | 入口点是 ReactDom.render,我们的应用程序是从这里开始渲染到 DOM 中的。为了方便调试,我创建了一个简单的 `` 组件。因此,发生的第一件事就是 **JSX 会被转换成 React 元素(element)**。它们是简单的、直白的对象。具有简单的结构。它们仅仅展示从本组件渲染中返回的内容,没有其他了。一些字段应该是你已经熟悉的,像 props、key 和 ref。属性类型是指由 JSX 描述的标记对象。所以,在我们的例子中,它就是 `ExampleApplication` 类,但是它也可以仅仅是 Button 标签的 `button` 字符串等其他类。另外,在 React 组件创建过程中,它会将 `defaultProps` 与 `props` 合并(如果显式声明了),并验证 `propTypes`。 11 | 12 | 更多详细信息可参考源码:`src\isomorphic\classic\element\ReactElement.js`。 13 | 14 | ### ReactMount 15 | 你可以看到一个叫做 `ReactMount`(01)的模块。它包含组件挂载的逻辑。实际上,在 `ReactDOM` 里面没有逻辑,它只是一个与`ReactMount` 一起使用的接口,所以当你调用 `ReactDOM.render` 的时候,实际上调用了 `ReactMount.render`。那“挂载”指的是什么呢? 16 | > 挂载是初始化 React 组件的过程。该过程通过创建组件所代表的 DOM 元素,并将它们插入到提供的 `container` 中来实现。 17 | 18 | 至少源码中的注释是这样描述的。那这真实的含义是什么呢?好吧,让我们想象一下下方的转换: 19 | 20 | 21 | [![图 0-1 JSX 到 HTML](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/mounting-scheme-1-small.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/mounting-scheme-1-small.svg) 22 | 23 | 24 | 25 | React 需要**将你的组件描述转换为 HTML** 以将其放入到 DOM 中。那怎样才能做到呢?没错,它需要处理所有的**属性、事件监听、内嵌的组件**和逻辑。它需要将你的高阶描述(组件)转换成实际可以放入到网页中的低阶数据(HTML)。这就是真正的挂载过程。 26 | 27 | 28 | [![图 0-2 JXS 到 HTML 2](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/mounting-scheme-1-big.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/mounting-scheme-1-big.svg) 29 | 30 | 31 | 32 | 让我们继续深入下去。接下来是有趣的事实时间!是的,让我们在探索过程中添加一些有趣的东西,让它变得更“有趣”。 33 | 34 | > 有趣的事实:确保滚动正在监听(02) 35 | 36 | > 有趣的是,在第一次渲染根组件时,React 初始化滚动监听并缓存滚动值,以便应用程序代码可以访问它们而不触发重排。实际上,由于浏览器渲染机制的不同,一些 DOM 值不是静态的,因此每次在代码中使用它们时都会进行计算。当然,这会影响性能。事实上,这只影响了不支持`pageX` 和 `pageY` 的旧版浏览器。React 也试图优化这一点。可以看到,制作一个运行快速的工具需要使用很多技术,这个滚动就是一个很好的例子。 37 | 38 | ### 实例化 React 组件 39 | 40 | 看下流程图,在图中(03)处标明了一个创建的实例。在这里创建一个 `` 的实例还为时过早。实际上该处实例化了 `TopLevelWrapper`(一个 React 内部的类)。让我们先来看看下面这个流程图。 41 | 42 | [![图 0-3 JSX 到 虚拟 DOM](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/jsx-to-vdom.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/jsx-to-vdom.svg) 43 | 44 | 45 | 46 | 你可以看到有三个部分,JSX 会被转换为 React 内部三种组件类型中的一种:`ReactCompositeComponent`(我们自定义的组件),`ReactDOMComponent`(HTML 标签)和 `ReactDOMTextComponent`(文本节点)。我们将略过描述`ReactDOMTextComponent` 并将重点放在前两个。 47 | 48 | 内部组件?这很有趣。你已经听说过 **虚拟 DOM** 了吧?虚拟 DOM 是一种 DOM 的表现形式。 React 用虚拟 DOM 进行组件差异计算等过程。该过程中无需直接操作 DOM 。这使得 React 在更新视图时候更快。但在 React 的源码中没有名为“Virtual DOM”的文件或者类。这是因为 虚拟DOM 只是一个概念,一种如何操作真实 DOM 的方法。所以,有些人说 虚拟DOM 元素等同于 React 组件,但在我看来,这并不完全正确。我认为虚拟 DOM 指的是这三个类:`ReactCompositeComponent`、`ReactDOMComponent` 和 `ReactDOMTextComponent`。后面你会知道到为什么。 49 | 50 | 好了,让我们在这里完成实例化过程。我们将创建一个 `ReactCompositeComponent` 实例,但实际上这并不是因为我们把`` 放在了 `ReactDOM.render` 里。React 总是从 `TopLevelWrapper` 开始渲染一棵组件的树。它几乎是一个空的包装器,其 `render` 方法(组件的 render)随后将返回 ``。 51 | ```javascript 52 | //src\renderers\dom\client\ReactMount.js#277 53 | TopLevelWrapper.prototype.render = function () { 54 | return this.props.child; 55 | }; 56 | 57 | ``` 58 | 59 | 所以,目前为止只有 `TopLevelWrapper` 被创建了。但是……先看一下一个有趣的事实。 60 | > 有趣的事实:验证 DOM 内嵌套 61 | 62 | > 几乎每次内嵌的组件渲染时,都被一个专门用于进行 HTML 验证的 `validateDOMNesting` 模块验证。DOM 内嵌验证指的是 `子标签 -> 父标签` 的标签层级的验证。例如,如果父标签是 ``)를 보존해서 예기치 못한 오류가 발생했을 때에도 그 input selection을 복원합니다. 36 | * DOM을 재배치하는 동안 이벤트를 비활성화하여 blurs/focuses를 막고, 이후에 이벤트 시스템이 다시 활성화되는것을 보장합니다. 37 | * 작업 쓰레드에서의 조정 이후에 큐에 쌓아놓았던 돔 변화를 메인 UI 쓰레드로 내보냅니다. 38 | * 새로운 내용을 렌더링 한 후 수집 된 `componentDidUpdate` 콜백을 호출합니다. 39 | 40 | 예시로 돌아가 보도록 합시다. 41 | 42 | 위에서 볼 수 있듯이, 리엑트는 `ReactDefaultBatchingStrategyTransaction`(1)을 사용합니다. 우리가 방금 지나온 것 것처럼, 트랜잭션에 대한 핵심은 래퍼입니다. 그렇기 때문에, 래퍼를 살펴보고 정의된 트랜잭션이 정확히 무엇인지 파악할 수 있습니다. 좋습니다. 여기 두 개의 래퍼가있습니다 : `FLUSH_BATCHED_UPDATES`,`RESET_BATCHED_UPDATES`. 한번 코드를 확인해 보도록 합시다 : 43 | 44 | ```javascript 45 | // \src\renderers\shared\stack\reconciler\ReactDefaultBatchingStrategy.js #19 46 | var RESET_BATCHED_UPDATES = { 47 | initialize: emptyFunction, 48 | close: function() { 49 | ReactDefaultBatchingStrategy.isBatchingUpdates = false; 50 | }, 51 | }; 52 | 53 | var FLUSH_BATCHED_UPDATES = { 54 | initialize: emptyFunction, 55 | close: ReactUpdates.flushBatchedUpdates.bind(ReactUpdates), 56 | } 57 | 58 | var TRANSACTION_WRAPPERS = [FLUSH_BATCHED_UPDATES, RESET_BATCHED_UPDATES]; 59 | ``` 60 | 61 | 어떻게 되어있는지 보이시나요. 이 트랜잭션에는 사전 조건이 없습니다. `initialize` 메소드는 비어 있지만, `close` 메소드 중 하나는 꽤 흥미롭습니다. 그것은 `ReactUpdates.flushBatchedUpdates`를 호출합니다. 이것은 무엇을 의미할까요? 이건 실제로 이후의 리렌더링을 통해 dirty 컴포넌트에 대한 검증을 시작합니다. 잘 따라 오셨죠? 마운팅 메소드를 호출하고 트랜잭션으로 랩핑합니다. 마운트 이후에 리엑트는 마운트 된 컴포넌트의 영향을 받는지 확인하고 업데이트합니다. 62 | 63 | 자, 다음은 트랜잭션에 랩핑된 메소드를 살펴 보겠습니다. 실제로, 이건 또 다른 트랜잭션으로 이어집니다... 64 | 65 | 66 | ### 좋습니다, 이제 우리는 *파트 1*를 끝냈습니다. 67 | 68 | 우리가 어떻게 여기까지 왔는지 다시 한번 살펴보도록 합시다. 스키마에서 덜 중요한 부분을 제거하면 다음과 같습니다. 69 | 70 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/1/part-1-A.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/1/part-1-A.svg) 71 | 72 | 1.3 간단히 보는 파트 1 (클릭 가능) 73 | 74 | 공백제거와 정렬을 통해 보기 좋게 수정했습니다. 75 | 76 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/1/part-1-B.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/1/part-1-B.svg) 77 | 78 | 1.4 간단히 보는 파트 1 리펙토링 버전 (클릭 가능) 79 | 80 | 좋습니다. 사실, 이것이 여기서 일어나는 일 전부입니다. 이제 *파트 1*의 핵심들을 가지고 최종 `mounting` 스키마에 사용할 수 있습니다. 81 | 82 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/1/part-1-C.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/1/part-1-C.svg) 83 | 84 | 1.5 파트 1의 핵심 (클릭 가능) 85 | 86 | 우리는 해냈습니다! 87 | 88 | 89 | [다음 페이지 : 파트 2 >>](./Part-2.md) 90 | 91 | [<< 이전 페이지 : 파트 0](./Part-0.md) 92 | 93 | 94 | [홈](../../README.md) 95 | -------------------------------------------------------------------------------- /stack/languages/korean/book/Part-10.md: -------------------------------------------------------------------------------- 1 | ## 파트 10 2 | 3 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/10/part-10.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/10/part-10.svg) 4 | 5 | 10.0 파트 10 (클릭 가능) 6 | 7 | ### Dirty components 8 | 9 | 보시다시피, 리엑트는 `dirtyComponents`(1)를 통해 루프를 수행하고, 트랜잭션을 통해 `ReactUpdates.runBatchedUpdates`(2)를 호출합니다. 또 하나의 새로운 트랜잭션이네요? 한번 살펴 보겠습니다. 10 | 11 | 트랜잭션의 타입은 `ReactUpdatesFlushTransaction`이며, 앞서 언급했듯이 트랜잭션이 실제로 무엇을 하는지 이해하기 위해서는 `wrappers`를 체크해봐야합니다. 코드의 주석에 힌트가 있습니다. 12 | > 'ReactUpdatesFlushTransaction의 래퍼는 dirtyComponents 배열을 지우고, 마운트 핸들러(예: componentDidUpdate)가 대기열에 추가 한 모든 업데이트를 수행합니다.' 13 | 14 | 그렇다면, 실제로 한번 확인해 봅시다. 여기에, 두 개의 래퍼 `NESTED_UPDATES`와 `UPDATE_QUEUEING`가 있습니다. `initialize` 단계에서 우리는 `dirtyComponentsLength`(3)'를 저장하고, `close`에서 검증할 수 있습니다. (리엑트는`initialize`에서 저장한 `dirtyComponentsLength`와 현재 `dirtyComponentsLength`를 비교합니다.) 업데이트 중에 플러시 된 dirty 컴포넌트의 수(dirtyComponentsLength)가 변경됬기 때문에, `flushBatchedUpdates`실행이 한 번 더 필요합니다. 보시다시피, 마법도 없고, 모든 것이 꽤 간단합니다. 15 | 16 | 음 .. 사실 한 번의 마법의 순간이 있습니다. `ReactUpdatesFlushTransaction`는 `Transaction.perform`메소드를 오버라이드합니다. 왜냐하면, 실제로는 `ReactReconcileTransaction`(트랜잭션은 마운트 중에 사용되며 앱 상태를 안전하게 유지할 수 있습니다.)의 동작이 필요하기 때문입니다. `ReactUpdatesFlushTransaction.perform` 메소드 내부에서 `ReactReconcileTransaction`도 사용되기 때문에, 실제로 트랜잭션 메소드가 한 번 더 래핑됩니다. 17 | 18 | 따라서, 기술적으로는, 다음과 같습니다: 19 | 20 | ```javascript 21 | [NESTED_UPDATES, UPDATE_QUEUEING].initialize() 22 | [SELECTION_RESTORATION, EVENT_SUPPRESSION, ON_DOM_READY_QUEUEING].initialize() 23 | 24 | method -> ReactUpdates.runBatchedUpdates 25 | 26 | [SELECTION_RESTORATION, EVENT_SUPPRESSION, ON_DOM_READY_QUEUEING].close() 27 | [NESTED_UPDATES, UPDATE_QUEUEING].close() 28 | ``` 29 | 마지막으로 이것이 메소드 작업을 끝내는데 어떻게 도움이되는지 다시 한번 확인하기 위해 트랜잭션으로 돌아가지만, 이제는 `ReactUpdates.runBatchedUpdates`(2)(`\src\renderers\shared\stack\reconciler\ReactUpdates.js #125`)의 세부 사항을 보도록하겠습니다. 30 | 31 | 우리가 처음부터해야 할 일은 `dirtyComponets`배열(4)을 정렬하는 것입니다. 어떻게 정렬을 할까요? `mount order`(인스턴스 마운트시 컴포넌트에 정수가 설정 됨)는 부모(먼저 마운트 된 것)가 먼저 업데이트되고, 다음으로 자식들이 업데이트된다는 것을 의미합니다. 다음 단계는 `updateBatchNumber`를 증가시키는 것입니다. 이건 현재 조정(reconciling)을 위한 ID와 같습니다. 코드의 주석에 따르면: 32 | 33 | > '조정하는 동안 대기열에 추가 된 모든 업데이트는 전체 일괄처리 이후에 수행되어야합니다. 그렇지 않으면, dirtyComponents가 [A, B]일때, A가 자식 B와 C를 갖는 경우, C의 렌더가 B(B가 이미 업데이트 되었으므로 이를 건너 뛰어야하며, 우리가 알 수있는 유일한 방법은 배치 카운터를 확인하는 것입니다.)에 대한 업데이트를 대기열에 넣으면 B는 단일 배치에서 두 번 업데이트 될 수 있습니다' 34 | 35 | 이건 실제로 동일한 컴포넌트에 대한 이중 업데이트를 피하는 데 도움이됩니다. 36 | 37 | 마지막으로 `dirtyComponents`를 루프 돌면서 각 컴포넌트를 `ReactReconciler.performUpdateIfNecessary`(5)로 전달합니다. 실제로 `performUpdateIfNecessary`메소드가 `ReactCompositeComponent`인스턴스에서 호출 될 것이므로 `ReactCompositeComponent` 코드와 그것의 메소드인 `updateComponent`로 이동하겠습니다. 여기서 흥미로운 것을 발견 할 수 있습니다. 이제 더 깊이 들어가 봅시다. 38 | 39 | ### 좋습니다, 이제 우리는 *파트 10*를 끝냈습니다. 40 | 41 | 우리가 어떻게 여기까지 왔는지 다시 한번 살펴보도록 합시다. 스키마에서 덜 중요한 부분을 제거하면 다음과 같습니다. 42 | 43 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/10/part-10-A.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/10/part-10-A.svg) 44 | 45 | 10.1 간단히 보는 파트 10 (클릭 가능) 46 | 47 | 공백을 처리하고 정렬을 통해 더 좋게 수정했습니다: 48 | 49 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/10/part-10-B.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/10/part-10-B.svg) 50 | 51 | 10.2 간단히 보는 파트 10 리펙토링 버전 (클릭 가능) 52 | 53 | 좋습니다. 사실, 이것이 여기서 일어나는 일 전부입니다. 이제 *파트 10*의 핵심들을 가지고 최종 `mounting` 스키마에 사용할 수 있습니다. 54 | 55 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/10/part-10-C.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/10/part-10-C.svg) 56 | 57 | 10.3 파트 10의 핵심 (클릭 가능) 58 | 59 | 우리는 해냈습니다! 60 | 61 | 62 | [다음 페이지 : 파트 11 >>](./Part-11.md) 63 | 64 | [<< 이전 페이지 : 파트 9](./Part-9.md) 65 | 66 | 67 | [홈](../../README.md) 68 | -------------------------------------------------------------------------------- /stack/languages/korean/book/Part-11.md: -------------------------------------------------------------------------------- 1 | ## 파트 11 2 | 3 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/11/part-11.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/11/part-11.svg) 4 | 5 | 11.0 파트 11 (클릭 가능) 6 | 7 | ### Update component 8 | 9 | 메소드를 설명하고 있는 코드의 주석입니다: 10 | > '마운팅된 컴포넌트의 업데이트를 수행합니다. componentWillReceiveProps와 shouldComponentUpdate메서드가 호출되면(업데이트를 건너 뛰지 않은 경우) 나머지 업데이트 라이프 사이클 메서드가 호출되고 DOM 표현이 업데이트됩니다. 기본적으로, 리엑트의 렌더링 및 조정 알고리즘을 사용합니다. 복잡한 클라이언트를 가진 프로젝트에서는 이것을 오버라이드해서 사용할 것입니다.' 11 | 12 | 좋습니다… 합리적인것 같네요. 13 | 14 | 우리는 가장먼저 `props`(1)가 변경되었는지 확인합니다. 기술적으로, `setState`가 호출되거나 `props`가 변경되는 두가지 시나리오로 `updateComponent`메소드가 호출 될 수 있습니다. 만약 `props`가 실제로 변경되면, 라이프 사이클 메소드인 `componentWillReceiveProps`가 호출 될 것입니다. 그 후, 리엑트는 `pending state queue`(우리가 전에 설정 한 부분 상태 객체의 대기열은 [{message : "click state message"}]와 같습니다.)에 기반하여 `nextState`(2)를 다시 계산합니다. 물론, 단지 `props`가 업데이트 되는 경우에는 `state`는 변경되지 않습니다. 15 | 16 | 다음 단계에서는 `shouldUpdate`의 디폴트값을 `true`(3)로 설정합니다. 실제로 `shouldComponentUpdate`가 지정되지 않은 경우에도 컴포넌트가 기본적으로 업데이트되는 이유입니다. 그런 다음 `force update`가 아닌지 확인합니다. 아시다시피, `state`나 `props`를 변경하는 대신 컴포넌트에서 `forceUpdate`를 호출하여 업데이트 할 수 있지만, 리엑트 공식 문서에 따르면 이 방법을 사용하지 않는것이 좋습니다. 따라서 강제 업데이트(force Update)의 경우 컴포넌트가 영구적으로 업데이트되며(번역 참고 : `shouldComponentUpdate`가 skip되어 호출되지 않습니다.([참고](https://facebook.github.io/react/docs/react-component.html#forceupdate))), 그렇지 않으면 명시된 컴포넌트에 `shouldComponentUpdate` 메소드가 호출되어 그 결과값이 `shouldUpdate`에 다시 할당됩니다. 컴포넌트가 `shouldUpdate`에 의해 업데이트가 필요없다고 판단되어지더라도, 리엑트는 여전히 `props`와 `state`를 설정해야 해야하지만, 그렇게 함으로써 남아있는 업데이트를 더 빠르게 할 수 있습니다. 17 | 18 | ### 좋습니다, 이제 우리는 *파트 11*를 끝냈습니다. 19 | 20 | 우리가 어떻게 여기까지 왔는지 다시 한번 살펴보도록 합시다. 스키마에서 덜 중요한 부분을 제거하면 다음과 같습니다. 21 | 22 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/11/part-11-A.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/11/part-11-A.svg) 23 | 24 | 11.1 간단히 보는 파트 11 (클릭 가능) 25 | 26 | 공백제거와 정렬을 통해 보기 좋게 수정했습니다. 27 | 28 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/11/part-11-B.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/11/part-11-B.svg) 29 | 30 | 11.2 간단히 보는 파트 11 리펙토링 버전 (클릭 가능) 31 | 32 | 좋습니다. 사실, 이것이 여기서 일어나는 일 전부입니다. 이제 *파트 11*의 핵심들을 가지고 최종 `updating` 스키마에 사용할 수 있습니다. 33 | 34 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/11/part-11-C.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/11/part-11-C.svg) 35 | 36 | 11.3 파트 11의 핵심 (클릭 가능) 37 | 38 | 우리는 해냈습니다! 39 | 40 | 41 | [다음 페이지: 파트 12 >>](./Part-12.md) 42 | 43 | [<< 이전 페이지: 파트 10](./Part-10.md) 44 | 45 | 46 | [홈](../../README.md) 47 | -------------------------------------------------------------------------------- /stack/languages/korean/book/Part-12.md: -------------------------------------------------------------------------------- 1 | ## 파트 12 2 | 3 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/12/part-12.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/12/part-12.svg) 4 | 5 | 12.0 파트 12 (클릭 가능) 6 | 7 | ### 실제로 컴포넌트를 업데이트 해야 하는 경우 8 | 9 | 업데이트의 초기단계이기 때문에, 만약 `componentWillUpdate` 정의가 되어있다면 그것을 호출하는데 적합한 위치입니다(1). 다음에는 컴포넌트를 리렌더링하고 `componentDidUpdate` 호출을 대기열에 추가합니다.(업데이트가 끝날 때 호출되어야 하기 때문에 호출을 연기합니다) 10 | 그렇다면 여기에서 리렌더링이란 무엇을 의미하는 것일까요? 사실, 여기서 해야 할 일은 컴포넌트의 `render` 메소드를 호출하고, 그에 따라 DOM을 업데이트하는 것입니다. 첫 번째는 인스턴스(`ExampleApplication`)에서`render`(2) 메소드를 호출하고 render의 결과(메소드 호출로 리턴된 리엑트 엘리먼트)를 저장하는 것입니다. 다음엔 이전에 렌더링 된 엘리먼트와 비교하여 DOM을 실제로 업데이트해야 하는지 확인합니다. 11 | 12 | 이건 리엑트의 주요 기능 중 하나인데, 이건 중복된 DOM 업데이트를 피해서 리엑트 성능을 향상시킵니다. 13 | `shouldUpdateReactComponent`(3) 메소드의 코드 주석 : 14 | > '기존 인스턴스가 새 인스턴스에 의해 제거되거나 대체되는 것이 아닌 기존 인스턴스를 수정해야 하는지 여부를 결정합니다.' 15 | 16 | 대략적으로 말하자면, 이 메소드는 엘리먼트를 완전히 대체해야 하는지 여부를 체크하는데, 이것은 우선 기존 엘리먼트를 `unmounted`하고, `mount` 메소드로부터 받은 새 엘리먼트(`render`에서 가져온)를 마운트 해서, 이 마운트 메소드로 부터 받은 마크업을 현재 엘리먼트 대신 배치하거나, 엘리먼트가 부분적으로 수정 될 수 있다는 것을 의미합니다. 엘리먼트를 완전히 대체하는 가장 큰 이유는 새로운 엘리먼트가 비어 있거나(`render` 로직에 의해 제거 된) 유형이 다른 경우인데, 예를 들면, 이전에는 `div`였지만 지금은 다른 것일 경우입니다. 코드를 봅시다. 간단합니다. 17 | 18 | ```javascript 19 | // /src/renderers/shared/shared/shouldUpdateReactComponent.js #25 20 | 21 | function shouldUpdateReactComponent(prevElement, nextElement) { 22 | var prevEmpty = prevElement === null || prevElement === false; 23 | var nextEmpty = nextElement === null || nextElement === false; 24 | if (prevEmpty || nextEmpty) { 25 | return prevEmpty === nextEmpty; 26 | } 27 | 28 | var prevType = typeof prevElement; 29 | var nextType = typeof nextElement; 30 | if (prevType === 'string' || prevType === 'number') { 31 | return (nextType === 'string' || nextType === 'number'); 32 | } else { 33 | return ( 34 | nextType === 'object' && 35 | prevElement.type === nextElement.type && 36 | prevElement.key === nextElement.key 37 | ); 38 | } 39 | } 40 | ``` 41 | 42 | 좋습니다. `ExampleApplication`의 경우 `render`에 영향을 주지않는 `state` property를 방금 업데이트했으므로, 두번째 시나리오인 `update`로 가봅시다. 43 | 44 | ### 좋습니다, 이제 우리는 *파트 12*를 끝냈습니다. 45 | 46 | 우리가 어떻게 여기까지 왔는지 다시 한번 살펴보도록 합시다. 스키마를 한번 더 보시고, 덜 중요한 부분을 제거하면 다음과 같습니다. 47 | 48 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/12/part-12-A.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/12/part-12-A.svg) 49 | 50 | 12.1 간단히 보는 파트 12 (클릭 가능) 51 | 52 | 공백을 처리하고 정렬을 통해 더 좋게 수정했습니다: 53 | 54 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/12/part-12-B.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/12/part-12-B.svg) 55 | 56 | 12.2 간단히 보는 파트 12 리펙토링 버전 (클릭 가능) 57 | 58 | 좋습니다. 사실, 이것이 여기서 일어나는 일 전부입니다. 이제 *파트 12*의 핵심들을 가지고 최종 `updating` 스키마에 사용할 수 있습니다. 59 | 60 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/12/part-12-C.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/12/part-12-C.svg) 61 | 62 | 12.3 파트 12의 핵심 (클릭 가능) 63 | 64 | 우리는 해냈습니다! 65 | 66 | 67 | [다음 페이지: 파트 13 >>](./Part-13.md) 68 | 69 | [<< 이전 페이지: 파트 11](./Part-11.md) 70 | 71 | 72 | [홈](../../README.md) 73 | -------------------------------------------------------------------------------- /stack/languages/korean/book/Part-13.md: -------------------------------------------------------------------------------- 1 | ## 파트 13 2 | 3 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/13/part-13.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/13/part-13.svg) 4 | 5 | 13.0 파트 13 (클릭 가능) 6 | 7 | ### Receive component(다음 엘리먼트, 보다 정확하게) 8 | 9 | `ReactReconciler.receiveComponent`를 통해 리엑트는 실제로 `ReactDOMComponent`에서 `receiveComponent`를 호출하고 그곳에서 다음 엘리먼트를 전달합니다. DOM 컴포넌트 인스턴스에 다음 엘리먼트를 다시 할당하고 update 메소드를 호출합니다. `updateComponent` 메소드는 실제로 `prev`와 `next` props를 기반으로 DOM properties와 DOM 자식을 업데이트하는 두 가지 주요 동작을 수행합니다. 우리는 이미 `_updateDOMProperties`(`src\renderers\dom\shared\ReactDOMComponent.js #946`)메소드를 분석했습니다. 이 메소드는 주로 HTML 요소의 properties와 attributes을 처리하고, 스타일을 계산하며, 이벤트 리스너를 처리합니다. 이제 남은 것은 `_updateDOMChildren`(`src\renderers\dom\shared\ReactDOMComponent.js #1076`)입니다. 10 | 11 | ### 좋습니다, 이제 우리는 *파트 13*를 끝냈습니다. 정말 짧았네요. 12 | 13 | 우리가 어떻게 여기까지 왔는지 다시 한번 살펴보도록 합시다. 스키마를 한번 더 보시고, 덜 중요한 부분을 제거하면 다음과 같습니다. 14 | 15 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/13/part-13-A.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/13/part-13-A.svg) 16 | 17 | 13.1 간단히 보는 파트 13 (클릭 가능) 18 | 19 | 공백을 처리하고 정렬을 통해 더 좋게 수정했습니다: 20 | 21 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/13/part-13-B.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/13/part-13-B.svg) 22 | 23 | 13.2 간단히 보는 파트 13 리펙토링 버전 (클릭 가능) 24 | 25 | 좋습니다. 사실, 이것이 여기서 일어나는 일 전부입니다. 이제 *파트 13*의 핵심들을 가지고 최종 `updating` 스키마에 사용할 수 있습니다. 26 | 27 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/13/part-13-C.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/13/part-13-C.svg) 28 | 29 | 13.3 파트 13의 핵심 (클릭 가능) 30 | 31 | 우리는 해냈습니다! 32 | 33 | 34 | [다음 페이지 : 파트 14 >>](./Part-14.md) 35 | 36 | [<< 이전 페이지 : 파트 12](./Part-12.md) 37 | 38 | 39 | [홈](../../README.md) 40 | -------------------------------------------------------------------------------- /stack/languages/korean/book/Part-2.md: -------------------------------------------------------------------------------- 1 | ## 파트 2 2 | 3 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/2/part-2.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/2/part-2.svg) 4 | 5 | 2.0 파트 2 (클릭 가능) 6 | 7 | ### 또 하나의 트랜젝션 8 | 9 | 이제는 `ReactReconcileTransaction`를 알아볼 시간입니다. 이미 알고 있겠지만, 트랜잭션 래퍼는 매우 흥미롭습니다. 여기 3개의 래퍼가 있습니다. 10 | 11 | ```javascript 12 | // \src\renderers\dom\client\ReactReconcileTransaction.js #89 13 | var TRANSACTION_WRAPPERS = [ 14 | SELECTION_RESTORATION, // 선택 복구 15 | EVENT_SUPPRESSION, // 이벤트 억제 16 | ON_DOM_READY_QUEUEING, // DOM 준비 대기열 17 | ]; 18 | ``` 19 | 20 | 보이는 것처럼 이 래퍼는 주로 메소드 호출 전에 **실제 상태를 유지**, 변경 가능한 값을 락하고 이후에 릴리즈합니다. 따라서 예를 들자면, 리엑트는 트랜잭션을 수행에 의해 선택 범위(현재 선택된 ``)가 방해받지 않는 것을 보장합니다.(`initialize`에서 선택된 것을 `close`에서 복원). 또한, DOM에서 높은 수준의 DOM 조작(예를 들면, 일시적으로 DOM에서 ``을 제거하는 것)으로 인해 실수로 발생 될 수 있는 이벤트(blur/focus)를 억제하기위해 `initialize` 할 때 **`ReactBrowserEventEmitter`를 사용하지 않게** 설정하고, close`할때 사용하게 합니다. 21 | 22 | 23 | 이제 DOM에 넣을 준비가 된 마크업을 리턴하는 컴포넌트 마운트를 시작하는데까지 거의 다 왔습니다. 실제로 `ReactReconciler.mountComponent`는 래퍼일 뿐이며, ‘중재인(mediator)’라고 말하는것이 더 정확합니다. 이건 컴포넌트 모듈로 마운팅하는 메소드를 위임합니다. 이건 정말 중요하니까 강조하도록 하겠습니다. 24 | 25 | 26 | > `ReactReconciler` 모듈은 어떤 로직의 구현이 **플랫폼에 의존**하는 경우에는 항상 호출됩니다. '메인 모듈'이 `ReactReconciler`에게 다음에 무엇을 해야할지 알려줍니다. 27 | 28 | 29 | 이제는 컴포넌트 메소드인 `mountComponent`로 넘어가봅시다. 아마 이미 들어본적이 있는 메소드 일겁니다. 이건 컴포넌트를 초기화하고, 마크업을 렌더링하며, 이벤트 리스너를 등록합니다. 보세요, 우리는 먼길을 지나 마침내 컴포넌트 마운팅이 호출되는것을 알 수 있습니다. 마운팅을 호출한 후에는, document에 넣을 수 있는 실제 HTML 엘리먼트를 가져와야합니다. 30 | 31 | 32 | 33 | ### 좋습니다, 이제 우리는 *파트 2*를 끝냈습니다. 34 | 35 | 우리가 어떻게 여기까지 왔는지 다시 한번 살펴보도록 합시다. 스키마에서 덜 중요한 부분을 제거하면 다음과 같습니다. 36 | 37 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/2/part-2-A.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/2/part-2-A.svg) 38 | 39 | 2.1 간단히 보는 파트 2 (클릭 가능) 40 | 41 | 공백제거와 정렬을 통해 보기 좋게 수정했습니다. 42 | 43 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/2/part-2-B.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/2/part-2-B.svg) 44 | 45 | 2.2 간단히 보는 파트 2 리펙토링 버전 (클릭 가능) 46 | 47 | 좋습니다. 사실, 이것이 여기서 일어나는 일 전부입니다. 이제 *파트 2*의 핵심들을 가지고 최종 `mounting` 스키마에 사용할 수 있습니다. 48 | 49 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/2/part-2-C.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/2/part-2-C.svg) 50 | 51 | 2.3 파트 2의 핵심 (클릭 가능) 52 | 53 | 우리는 해냈습니다! 54 | 55 | 56 | [다음 페이지 : 파트 3 >>](./Part-3.md) 57 | 58 | [<< 이전 페이지 : 파트 1](./Part-1.md) 59 | 60 | 61 | [홈](../../README.md) 62 | -------------------------------------------------------------------------------- /stack/languages/korean/book/Part-3.md: -------------------------------------------------------------------------------- 1 | ## 파트 3 2 | 3 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/3/part-3.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/3/part-3.svg) 4 | 5 | 3.0 파트 3 (클릭 가능) 6 | 7 | ### 마운트(Mount) 8 | 9 | `componentMount` 메소드는 이 여정에서 가장 큰 부분 중 하나입니다! 그래서, `ReactCompositeComponent.mountComponent`(1)는 흥미로운 메소드 입니다. 10 | 11 | 기억하시겠지만, **컴포넌트의 트리에 처음 삽입되는** 컴포넌트는`TopLevelWrapper`(내부 리엑트 클래스)라고 한 적이 있었습니다. 이제 그것 마운팅 하려고 합니다. 하지만, 이건 사실 비어있는 래퍼이므로 디버깅이 좀 지루합니다. 지금 흐름에 전혀 영향을 주지 않기 때문에 지금은 이걸 건너 뛰고 자식으로 이동하겠습니다. 12 | 13 | 부모와 그 부모의 자식, 그 자식의 자식을 계속해서 마운트하는 것이 트리의 마운팅이 실제로 하는 일입니다. 저를 믿으세요, `TopLevelWrapper`가 마운트 된 후에, 그것(ExampleApplication 컴포넌트를 관리하는`ReactCompositeComponent`)의 자식도 같은 단계에 놓이게됩니다. 14 | 15 | 좋습니다, 이제 다시 step(1)로 돌아갑시다. 안에 뭐가 있는지 봅시다. 몇 가지 주요 동작이 발생하므로, 자세하게 이 로직을 살펴 보겠습니다. 16 | 17 | ### 인스턴스 updater 할당 18 | 19 | `transaction.getUpdateQueue()`에서 리턴되는 `updater`(2)는 사실 `ReactUpdateQueue` 모듈입니다. 그런데 `updater`가 왜 **여기서 할당**될까요? `ReactCompositeComponent`(우리가 현재보고있는 클래스)는 모든 플랫폼에서 사용되지만, updater는 그렇지 않기 때문에 플랫폼에 따라 마운팅되는 동안 동적으로 할당합니다. 20 | 21 | 지금은 `updater`가 필요하지 않지만 기억해 두십시오. `updater`는 정말 **중요**합니다. 잘 알려진 컴포넌트 메소드인 **`setState`**에 의해 곧 사용될 것입니다. 22 | 23 | 이 단계에서 인스턴스에 `updater`가 할당될뿐만 아니라 컴포넌트 인스턴스(사용자 정의 컴포넌트)도 `props`, `context`, `refs`로 확장됩니다. 24 | 25 | 아래 코드를 확인하십시오 : 26 | 27 | ```javascript 28 | // \src\renderers\shared\stack\reconciler\ReactCompositeComponent.js #255 29 | // 이것들은 생성자안에서 설정되어야하지만, 30 | // 좀더 단순한 클래스 추상화의 편의를 위해, 생성자 이후에 설정했다. 31 | inst.props = publicProps; 32 | inst.context = publicContext; 33 | inst.refs = emptyObject; 34 | inst.updater = updateQueue; 35 | ``` 36 | 37 | 이제, `this.props`로 인스턴스의 `props`에 접근 할 수 있습니다. 38 | 39 | ### ExampleApplication 인스턴스 생성 40 | 41 | `_constructComponent`(3)을 호출하고 여러 가지 구성 메소드를 통해 마침내 `new ExampleApplication()`이 생성됩니다. 생성자가 호출 될 때가 중요합니다. 이 시점이 리엑트의 생태계로 부터 실제로 영향을 받은 첫번째 순간 입니다. 42 | 43 | ### 초기 마운트 수행 44 | 45 | mount(4)를 지나면, 먼저 `componentWillMount`(명시된 경우)가 호출됩니다. 이건 라이프 사이클 훅의 첫 번째 메소드입니다. 또한, 뒤에서 `componentDidMount`를 볼 수 있지만 직접 호출되어서는 안되기 때문에 트랜잭션 대기열에 넣습니다. 이건 마운트 작업이 끝나는 마지막에만 발생합니다. `setState` 호출은 `componentWillMount` 안에서도 할 수 있습니다. 이 경우에는 `render`메소드 없이 state가 다시 계산됩니다.(컴포넌트가 아직 마운트되지 않았기 때문에 state를 알 수 없습니다). 46 | 47 | 공식 문서에서 다음과 같이 작성되어 있습니다: 48 | 49 | > `componentWillMount()`는 마운트가 일어나기 직전에 호출된다. `render()`전에 호출되기 때문에, 이 메소드의 state를 설정해도 리렌더링이 발생되지 않는다. 50 | 51 | 코드를 확인해 봅시다. 52 | 53 | ```javascript 54 | // \src\renderers\shared\stack\reconciler\ReactCompositeComponent.js #476 55 | if (inst.componentWillMount) { 56 | //.. 57 | inst.componentWillMount(); 58 | 59 | // 마운트 할 때,`componentWillMount`에 의한 `setState`호출은 리렌더링을 하지 않고, 60 | // `this._pendingStateQueue`를 설정합니다. 61 | if (this._pendingStateQueue) { 62 | inst.state = this._processPendingState(inst.props, inst.context); 63 | } 64 | } 65 | ``` 66 | 67 | `state`가 다시 계산 될 때 `render`메소드를 호출합니다. 정확히는 사용자가 컴포넌트에서 지정하는 것입니다! 이제 한번 더 코드에 손대봅시다. 68 | 69 | 다음은 리엑트 컴포넌트 인스턴스를 만드는 것입니다. 또 하는것 같나요? 이미 `this._instantiateReactComponent`(5) 호출을 본 것 같습니다. 맞나요? 사실이지만, 그때는 `ExampleApplication` 컴포넌트에 대해 `ReactCompositeComponent`를 인스턴스화했습니다. 이제 `render`메소드에서 얻은 엘리먼트를 기반으로 그 자식에 대한 VDOM 인스턴스를 생성 할 것입니다. 정확하게는 render 메서드는 `div`를 반환하므로 VDOM 표현은 `ReactDOMComponent`입니다. 인스턴스가 생성되면, `ReactReconciler.mountComponent`를 다시 호출합니다. 하지만 이번에는 `internalInstance`로 새로 생성 된 `ReactDOMComponent`의 인스턴스를 전달합니다. 70 | 71 | 그리고,`mountComponent`를 호출합니다. 72 | 73 | ### 좋습니다, 이제 우리는 *파트 3*를 끝냈습니다. 74 | 75 | 우리가 어떻게 여기까지 왔는지 다시 한번 살펴보도록 합시다. 스키마에서 덜 중요한 부분을 제거하면 다음과 같습니다. 76 | 77 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/3/part-3-A.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/3/part-3-A.svg) 78 | 79 | 3.1 간단히 보는 파트 3 (클릭 가능) 80 | 81 | 공백제거와 정렬을 통해 보기 좋게 수정했습니다. 82 | 83 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/3/part-3-B.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/3/part-3-B.svg) 84 | 85 | 3.2 간단히 보는 파트 3 리펙토링 버전 (클릭 가능) 86 | 87 | 좋습니다. 사실, 이것이 여기서 일어나는 일 전부입니다. 이제 *파트 3*의 핵심들을 가지고 최종 `mounting` 스키마에 사용할 수 있습니다. 88 | 89 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/3/part-3-C.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/3/part-3-C.svg) 90 | 91 | 3.3 파트 3의 핵심 (클릭 가능) 92 | 93 | 그리고 이제 우리는 해냈습니다! 94 | 95 | 96 | [다음 페이지 : 파트 4 >>](./Part-4.md) 97 | 98 | [<< 이전 페이지 : 파트 2](./Part-2.md) 99 | 100 | 101 | [홈](../../README.md) 102 | -------------------------------------------------------------------------------- /stack/languages/korean/book/Part-4.md: -------------------------------------------------------------------------------- 1 | ## 파트 4 2 | 3 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/4/part-4.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/4/part-4.svg) 4 | 5 | 4.0 파트 4 (클릭 가능) 6 | 7 | ### 자식 마운팅 8 | 9 | 계속해서 `mount` 메소드를 알아보도록 합시다. 10 | 11 | `_tag`에 video, form, textarea 등과 같은 '복잡한' 태그(1)가 포함되어 있으면 추가 래핑이 필요합니다. `audio` 태그를 위한 'volumechange' 같이 각각의 미디어 이벤트에 대한 이벤트 리스너를 추가하거나 `select`, `textarea` 등에는 태그의 기본 동작을 래핑합니다. 12 | `ReactDOMSelect`, `ReactDOMTextarea`(src\renderers\dom\client\wrappers\ 폴더 내부)과 같은 엘리먼트를 위한 래퍼가 많이 있습니다. 지금의 경우는 단지 `div`이고, 추가 처리는 없습니다. 13 | 14 | ### Props 유효성 검사 15 | 16 | 다음으로, 유효성 검사 메서드는 단지 내부 `props`가 올바르게 설정되었는지를 확인하기 위해 호출됩니다. 설정이 잘 안되어 있으면 오류가 발생합니다. 예를 들어 `props.dangerouslySetInnerHTML`가 설정(보통 문자열에서 HTML을 삽입하려고 할 때 그렇게합니다)되고 객체 키 `__html`이 누락되면 다음과 같은 오류가 발생합니다. 17 | 18 | > `props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. Please visit https://fb.me/react-invariant-dangerously-set-inner-html for more information. 19 | 20 | ### HTML 엘리먼트 생성 21 | 22 | `div`를 인스턴스화를 하는 `document.createElement`에 의해 실제 HTML 엘리먼트가 생성됩니다(3). 이전에 우리는 가상 표현(VDOM)으로만 작업했지만 이제는 처음으로 실제 HTML을 볼 수 있게 되었습니다. 23 | 24 | 25 | ### 좋습니다, 이제 우리는 *파트 4*를 끝냈습니다. 26 | 27 | 우리가 어떻게 여기까지 왔는지 다시 한번 살펴보도록 합시다. 스키마에서 덜 중요한 부분을 제거하면 다음과 같습니다. 28 | 29 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/4/part-4-A.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/4/part-4-A.svg) 30 | 31 | 4.1 간단히 보는 파트 4 (클릭 가능) 32 | 33 | 공백제거와 정렬을 통해 보기 좋게 수정했습니다. 34 | 35 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/4/part-4-B.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/4/part-4-B.svg) 36 | 37 | 4.2 간단히 보는 파트 4 리펙토링 버전 (클릭 가능) 38 | 39 | 좋습니다. 사실, 이것이 여기서 일어나는 일 전부입니다. 이제 *파트 4*의 핵심들을 가지고 최종 `mounting` 스키마에 사용할 수 있습니다. 40 | 41 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/4/part-4-C.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/4/part-4-C.svg) 42 | 43 | 4.3 파트 4의 핵심 (클릭 가능) 44 | 45 | 우리는 해냈습니다! 46 | 47 | 48 | [다음 페이지 : 파트 5 >>](./Part-5.md) 49 | 50 | [<< 이전 페이지 : 파트 3](./Part-3.md) 51 | 52 | 53 | [홈](../../README.md) 54 | -------------------------------------------------------------------------------- /stack/languages/korean/book/Part-5.md: -------------------------------------------------------------------------------- 1 | ## 파트 5 2 | 3 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/5/part-5.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/5/part-5.svg) 4 | 5 | 5.0 파트 5 (클릭 가능) 6 | 7 | ### DOM properties 업데이트 8 | 9 | 무서워 보이죠? 위의 스키마의 핵심은 이전과 새로운 `props`의 diff를 효율적으로 적용하고 있다는 것입니다. 코드에서 메소드에 달린 주석을 살펴보십시오. 10 | > "property 값들의 차이점을 감지하고 필요하다면 DOM을 업데이트하여 properties를 조정한다. 이 함수는 성능 최적화를 위한 가장 중요한 단일경로이다." 11 | 12 | 여기에는 두 개의 루프가 있습니다. 이전 `props` 통하는 것과 다음 `props`를 통하는 것입니다. 우리의 경우 마운트에서 `lastProps`(이전)는 비어 있습니다(처음으로 props를 할당하기 때문에). 여기에서 무슨 일이 일어나는지 보도록 하겠습니다. 13 | 14 | ### 이전 `props` 루프 15 | 첫 번째 단계에서 우리는 `nextProps`가 같은 prop 값을 가졌는지 확인합니다. 만약 그렇다면 `nextProps` 루프에서 나중에 처리될 것이므로 그냥 건너뜁니다. 그런 다음 스타일 값을 재설정하고, 이벤트 리스너(이전에 설정 한 경우)를 삭제하고, DOM attribute 와 DOM properties 값을 제거합니다. attribute 의 경우, `RESERVED_PROPS`가 아니라 `children` 또는 `dangerouslySetInnerHTML`과 같은 실제 `prop`인지 확인합니다. 16 | 17 | ### 다음 `props` 루프 18 | 여기서는 가장 먼저 `prop`가 변경되었는지 즉, 다음 값이 이전 값과 다른지 확인합니다. 그렇지 않다면, 아무 것도 하지 않습니다. `styles`의 경우 (스타일은 조금 특별하게 취급되는 것을 눈치챘을 것입니다.) `lastProp` 이후에 변경된 값들을 업데이트합니다. 그후 이벤트 리스너를 추가합니다(예를 들어,`onClick` 과 같은 것들). 자세한 내용을 분석해 봅시다. 19 | 20 | 리엑트에서는 모든 작업이 ‘결합(synthetic)’이라는 이벤트를 통과한다는 것이 중요합니다. 좀 더 효율적인 작업을 위한 래퍼일 뿐, 별로 특별할 건 없습니다. 다음으로, 이벤트 리스너를 관리하기 위한 중재인(mediator) 모듈은 `EventPluginHub` (`src\renderers\shared\stack\event\EventPluginHub.js`)입니다. 이것은 모든 리스너를 캐싱하고 관리하기 위한 `listenerBank` 맵을 포함합니다. 21 | 이벤트 리스너를 추가 할 예정이지만 지금 하지는 않습니다. 핵심은 컴포넌트와 DOM 엘리먼트가 이벤트를 처리 할 준비가 되었을 때 리스너를 추가해야한다는 것입니다. 준비된 시점을 어떻게 알수 있는지 궁금하고, 이 부분이 실행을 지연시키는 것처럼 보이지만 모든 메소드와 호출들을 `transaction`에 전달했던것을 기억하고 계십니까? 이러한 상황을 위해 그렇게했었습니다. 코드에서 그 증거를 봅시다. 22 | 23 | ```javascript 24 | // src\renderers\dom\shared\ReactDOMComponent.js #222 25 | transaction.getReactMountReady().enqueue(putListener, { 26 | inst: inst, 27 | registrationName: registrationName, 28 | listener: listener, 29 | }); 30 | ``` 31 | 32 | 이벤트 리스너를 추가한 후에 DOM attribute과 DOM property 값을 설정합니다. 이전과 마찬가지로 attributes가 `RESERVED_PROPS` 가 아니고, `children`, `dangerouslySetInnerHTML`와 같은 실제 `prop`인지 확인합니다. 33 | 34 | 마지막으로 다음 props을 처리하는 동안 `styleUpdates` 설정을 계산하고 그것을 `CSSPropertyOperations` 모듈에 전달합니다. 35 | 36 | 이제 properties 업데이트를 마쳤습니다. 계속 가보도록 합시다. 37 | 38 | ### 좋습니다, 이제 우리는 *파트 5*를 끝냈습니다. 39 | 40 | 우리가 어떻게 여기까지 왔는지 다시 한번 살펴보도록 합시다. 스키마에서 덜 중요한 부분을 제거하면 다음과 같습니다. 41 | 42 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/5/part-5-A.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/5/part-5-A.svg) 43 | 44 | 5.1 간단히 보는 파트 5 (클릭 가능) 45 | 46 | 공백제거와 정렬을 통해 보기 좋게 수정했습니다. 47 | 48 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/5/part-5-B.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/5/part-5-B.svg) 49 | 50 | 5.2 간단히 보는 파트 5 리펙토링 버전 (클릭 가능) 51 | 52 | 좋습니다. 사실, 이것이 여기서 일어나는 일 전부입니다. 이제 *파트 5*의 핵심들을 가지고 최종 `mounting` 스키마에 사용할 수 있습니다. 53 | 54 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/5/part-5-C.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/5/part-5-C.svg) 55 | 56 | 5.3 파트 5의 핵심 (클릭 가능) 57 | 58 | 우리는 해냈습니다! 59 | 60 | 61 | [다음 페이지 : 파트 6 >>](./Part-6.md) 62 | 63 | [<< 이전 페이지 : 파트 4](./Part-4.md) 64 | 65 | 66 | [홈](../../README.md) 67 | -------------------------------------------------------------------------------- /stack/languages/korean/book/Part-6.md: -------------------------------------------------------------------------------- 1 | ## 파트 6 2 | 3 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/6/part-6.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/6/part-6.svg) 4 | 5 | 6.0 파트 6 (클릭 가능) 6 | 7 | ### 초기 자식(children) 생성 8 | 9 | 이제 엘리먼트가 완성된 것처럼 보입니다, 이제 자식들과 함께할 수 있습니다. 여기 두 단계가 있습니다. 자식들은 (`this.mountChildren`)(1)에 마운트 되어야 하고, 부모(`DOMLazyTree.queueChild`)(2)에 연결되어야 합니다. 자식들의 마운팅이 분명히 더 재미있을 것이기 때문에 그쪽으로 이동해 봅시다. 10 | 11 | 자식들을 관리하기 위한 `ReactMultiChild` (`src\renderers\shared\stack\reconciler\ReactMultiChild.js`)라 별도의 모듈이 있습니다. 이제 `mountChildren` 메소드를 확인해 봅시다. 여기에는 두 가지 주요 작업이 포함됩니다. 우선, 자식들을 인스턴스화하고(이를 위해 `ReactChildReconciler`를 사용) 그들을 마운트합니다. 실제로 어떤 자식들이 여기에 있을까요? 그건 단순한 HTML 태그이거나 다른 커스텀 컴포넌트 일 수 있습니다. HTML을 처리하기 위해 `ReactDOMComponent`를 인스턴스화하고 커스텀 컴포넌트를 위해서는 `ReactCompositeComponent`를 인스턴스화해야 합니다. 다시 말하자면, 마운트 흐름(flow)은 하위 유형(type)이 무엇인지에 따라 달라집니다. 12 | 13 | ### 다시 한번 더 봅시다. 14 | 15 | 만약 당신이 이 글을 아직 읽고 있다면, 아마도 전체 프로세스를 한 번 더 명확히 검토해야 할 때입니다. 객체의 순서를 되새겨 봅시다. 16 | 17 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/6/overall-mounting-scheme.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/6/overall-mounting-scheme.svg) 18 | 19 | 6.1 전반적인 마운팅 스키마 (클릭 가능) 20 | 21 | 1) 리엑트는 각각의 커스텀 컴포넌트(`componentWillMount` 등과 같은 컴포넌트 라이프 사이클 훅을 포함한)를 위해 `ReactCompositeComponent`를 인스턴스화하고 마운트합니다. 22 | 23 | 2) 마운트하는 과정 중에 가장 먼저 커스텀 컴포넌트의 인스턴스가 생성됩니다.(`constructor`가 호출 됨). 24 | 25 | 3) 그런 다음 render 메소드가 호출되고(간단한 예를 들면, render는 `div`를 리턴합니다), `React.createElement`는 리엑트 요소를 만듭니다. 리엑트 요소는 직접 호출 되거나, JSX가 Babel에 의해 파싱된 후에 호출 될 수 있고, 랜더시 태그를 대체(replacing) 할 수도 있지만 이러한 부분들은 현재 필요로하는 것이 아닙니다. 아래의 내용을보십시오. 26 | 27 | 4) `div`위한 DOM 컴포넌트가 필요합니다. 그래서 인스턴스화 과정에서 엘리먼트 객체(위에서 언급한)로부터 `ReactDOMComponent`의 인스턴스를 생성합니다. 28 | 29 | 5) 그런 다음 DOM 컴포넌트를 마운트해야합니다. 이는 실제로 DOM 엘리먼트를 만들고 이벤트 리스너등을 할당한다는 것을 의미합니다. 30 | 31 | 6) 이제, DOM 컴포넌트의 초기 자식 항목들을 처리합니다. 자식들의 인스턴스를 생성하고 마운트합니다. 각각의 자식들의 항목이 커스텀 컴포넌트인 경우 1단계 부터 반복하고, HTML 태그인경우 5단계 부터 반복합니다. 그리고 모든 내부 엘리먼트들에게도 적용됩니다. 32 | 33 | 이게 전부입니다. 보시는 것처럼 꽤 간단합니다. 34 | 35 | 이제 기본적으로 마운팅은 완료되었습니다. `componentDidMount` 메소드를 대기열에 넣으십시오! 잘 하셨습니다. 36 | 37 | ### 좋습니다, 이제 우리는 *파트 6*를 끝냈습니다. 38 | 39 | 우리가 어떻게 여기까지 왔는지 다시 한번 살펴보도록 합시다. 스키마에서 덜 중요한 부분을 제거하면 다음과 같습니다. 40 | 41 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/6/part-6-A.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/6/part-6-A.svg) 42 | 43 | 6.2 간단히 보는 파트 6 (클릭 가능) 44 | 45 | 공백을 처리하고 정렬을 통해 더 좋게 수정했습니다. 46 | 47 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/6/part-6-B.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/6/part-6-B.svg) 48 | 49 | 6.3 간단히 보는 파트 6 리펙토링 버전 (클릭 가능) 50 | 51 | 좋습니다. 사실, 이것이 여기서 일어나는 일 전부입니다. 이제 *파트 6*의 핵심들을 가지고 최종 `mounting` 스키마에 사용할 수 있습니다. 52 | 53 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/6/part-6-C.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/6/part-6-C.svg) 54 | 55 | 6.4 파트 6의 핵심 (클릭 가능) 56 | 57 | 우리는 해냈습니다! 58 | 59 | 60 | [다음 페이지 : 파트 7 >>](./Part-7.md) 61 | 62 | [<< 이전 페이지 : 파트 5](./Part-5.md) 63 | 64 | 65 | [홈](../../README.md) 66 | -------------------------------------------------------------------------------- /stack/languages/korean/book/Part-7.md: -------------------------------------------------------------------------------- 1 | ## 파트 7 2 | 3 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/7/part-7.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/7/part-7.svg) 4 | 5 | 7.0 파트 7 (클릭 가능) 6 | 7 | ### 처음으로 돌아가기 8 | 9 | 메소드 실행의 결과로 인한 마운팅 이후에 document에 세팅할 준비가 된 HTML 엘리먼트를 가질 수 있습니다. `mountComponent`에 의해 `markup`(1)이 생성되었지만, 이 `markup`(1)은 실제 HTML 마크업이 아닙니다. `children`, `node`(실제 DOM 노드)등의 필드를 가진 데이터 구조입니다. 그러나 컨테이너(`ReactDOM.render` 호출에서 컨테이너로 지정된)에 넣을 HTML 엘리먼트는 있습니다. 리엑트는 `markup`(1)를 DOM에 추가하는 동안 이전에 있던 모든 것을 지울것입니다. `DOMLazyTree`(2)는 트리 데이터 구조로 DOM 조작을 하는 중에 몇 가지 연산을 수행하는 util 클래스입니다. 10 | 11 | 마지막으로 볼건 `parentNode.insertBefore (tree.node)`(3)입니다. `parentNode`는 컨테이너`div` 노드이고 `tree.node`는 `ExampleAppliication` div 노드입니다. 마운팅 중 생성된 HTML 엘리먼트는 마침내 document에 삽입되었습니다. 12 | 13 | 이게 끝일까요? 그렇지 않습니다. 기억하고 있듯이, 래핑된 `mount` 호출은 트랜잭션에 안에 있습니다. 그렇다면 우리는 그걸 클로즈해야 한다는 것을 의미합니다. `close` 래퍼 리스트를 확인해 봅시다. 락을 해놓은 `ReactInputSelection.restoreSelection()`, `ReactBrowserEventEmitter.setEnabled(previousEnabled)`를 복원하고, 이전에 `transaction.reactMountReady`대기열에 넣은 모든 콜백을 `this.reactMountReady.notifyAll`(4)로 알려야 할 것입니다. 그 중 하나는 우리가 가장 잘 알고있는 `componentDidMount`이며, 이는 `close` 래퍼에 의해 트리거 될 것입니다. 14 | 15 | 이제 '컴포넌트가 실제로 마운팅 된 것'에 대한 명확한 그림을 얻었습니다. 건배! 16 | 17 | ### 트랜젝션 클로즈 한번 더 18 | 19 | 사실, 트랜젝션은 하나만 있는게 아닙니다. `ReactMount.batchedMountComponentIntoNode` 호출을 래핑하는데 사용 된 트랜젝션을 잊고 있었습니다. 그것을 클로즈 하도록 합시다. 20 | 21 | 여기에서는 `dirtyComponents`를 처리하는 `ReactUpdates.flushBatchedUpdates`(5) 래퍼를 검사합니다. 흥미롭지 않은가요? 좋든 나쁘든, 우리는 처음 마운트를 했으므로 dirty components가 아직 없습니다. 그것은 빈 호출을 의미합니다. 따라서 이 트랜잭션 또한 클로즈하고 batching strategy updates가 완료되었다고 말할 수 있습니다. 22 | 23 | ### 좋습니다, 이제 우리는 *파트 7*를 끝냈습니다. 24 | 25 | 우리가 어떻게 여기까지 왔는지 다시 한번 살펴보도록 합시다. 스키마에서 덜 중요한 부분을 제거하면 다음과 같습니다. 26 | 27 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/7/part-7-A.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/7/part-7-A.svg) 28 | 29 | 7.1 간단히 보는 파트 7 (클릭 가능) 30 | 31 | 공백제거와 정렬을 통해 보기 좋게 수정했습니다. 32 | 33 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/7/part-7-B.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/7/part-7-B.svg) 34 | 35 | 7.2 간단히 보는 파트 7 리펙토링 버전 (클릭 가능) 36 | 37 | 좋습니다. 사실, 이것이 여기서 일어나는 일 전부입니다. 이제 *파트 7*의 핵심들을 가지고 최종 `mounting` 스키마에 사용할 수 있습니다. 38 | 39 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/7/part-7-C.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/7/part-7-C.svg) 40 | 41 | 7.3 파트 7의 핵심 (클릭 가능) 42 | 43 | 우리는 해냈습니다! 사실 우리는 마운팅을 끝냈습니다. 아래를 보십시오. 44 | 45 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/7/mounting-parts-C.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/7/mounting-parts-C.svg) 46 | 47 | 7.4 마운팅 (클릭 가능) 48 | 49 | [다음 페이지 : 파트 8 >>](./Part-8.md) 50 | 51 | [<< 이전 페이지 : 파트 6](./Part-6.md) 52 | 53 | 54 | [홈](../../README.md) 55 | -------------------------------------------------------------------------------- /stack/languages/korean/book/Part-8.md: -------------------------------------------------------------------------------- 1 | ## 파트 8 2 | 3 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/8/part-8.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/8/part-8.svg) 4 | 5 | 8.0 파트 8 (클릭 가능) 6 | 7 | ### `this.setState` 8 | 9 | 우리는 이제 마운팅이 어떻게 작동하는지 알고 있으니, 다른 파트도 알아보도록 합시다. 바로, `setState`메소드 입니다! 10 | 11 | `setState`메소드를 호출할 수 있는 이유는 무엇일까요? 그건 분명, `ReactComponent`로 부터 컴포넌트를 상속받았기 때문입니다. 그렇다면 이제 리엑트 소스코드에서 이 클래스를 찾아 `setState`메소드를 확인하는 것은 쉽습니다. 12 | 13 | ```javascript 14 | // src\isomorphic\modern\class\ReactComponent.js #68 15 | this.updater.enqueueSetState(this, partialState) 16 | ``` 17 | 보시다시피, 여기 `updater` 인터페이스가 있습니다. `updater`란 뭔가요? 우리가 방금 분석 한 마운팅 프로세스를 확인해보면, `mountComponent` 하는 동안, 인스턴스는 `ReactUpdateQueue`(`src\renderers\shared\stack\reconciler\ReactUpdateQueue.js`)를 참조하는 `updater` property를 받습니다. 18 | 19 | `enqueueSetState`(1) 메소드 안으로 들어가서 봅시다. 우선 부분상태(partial state: `this.setState`에 전달하는 객체)를 내부 인스턴스 `_pendingStateQueue`(2)로 푸시합니다.(되집어 봅시다: public 인스턴스는 실제로 커스텀 컴포넌트인 `ExampleApplication`이고, 내부 인스턴스는 마운트 중에 생성 된 `ReactCompositeComponent`입니다.). 다음엔, `enqueueUpdate` 입니다. 실제로 진행중인 업데이트가 있다면 컴포넌트를 `dirtyComponents`리스트에 넣고, 그렇지 않다면 - update transaction 초기화 하고, `dirtyComponents`리스트에 컴포넌트를 넣습니다. 20 | 21 | 요약하자면, 각 컴포넌트는 자신의 보류 상태(pending states)의 목록을 가지고 있습니다. 즉, 하나의 트랜잭션에서 `setState`를 호출 할 때마다 그 객체를 대기열에 넣은 다음 나중에 하나씩 컴포넌트 상태(state)로 머지합니다. 그리고 `setState`를 호출하면, 컴포넌트를 `dirtyComponents`리스트에 추가 됩니다. 아마 `dirtyComponents`가 어떻게 처리되는지 궁금할것입니다. 맞습니다. 그것이 이 프로세스 중요한 부분입니다. 22 | 23 | ### 좋습니다, 이제 우리는 *파트 8*를 끝냈습니다. 24 | 25 | 우리가 어떻게 여기까지 왔는지 다시 한번 살펴보도록 합시다. 스키마에서 덜 중요한 부분을 제거하면 다음과 같습니다. 26 | 27 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/8/part-8-A.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/8/part-8-A.svg) 28 | 29 | 8.1 간단히 보는 파트 8 (클릭 가능) 30 | 31 | 공백제거와 정렬을 통해 보기 좋게 수정했습니다. 32 | 33 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/8/part-8-B.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/8/part-8-B.svg) 34 | 35 | 8.2 간단히 보는 파트 8 리펙토링 버전 (클릭 가능) 36 | 37 | 좋습니다. 사실, 이것이 여기서 일어나는 일 전부입니다. 이제 *파트 8*의 핵심들을 가지고 최종 `updating` 스키마에 사용할 수 있습니다. 38 | 39 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/8/part-8-C.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/8/part-8-C.svg) 40 | 41 | 8.3 파트 8의 핵심 (클릭 가능) 42 | 43 | 우리는 해냈습니다! 44 | 45 | 46 | [다음 페이지 : 파트 9 >>](./Part-9.md) 47 | 48 | [<< 이전 페이지 : 파트 7](./Part-7.md) 49 | 50 | 51 | [홈](../../README.md) 52 | -------------------------------------------------------------------------------- /stack/languages/korean/book/Part-9.md: -------------------------------------------------------------------------------- 1 | ## 파트 9 2 | 3 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/9/part-9.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/9/part-9.svg) 4 | 5 | 9.0 파트 9 (클릭 가능) 6 | 7 | ### 다시 돌아가봅시다. 8 | 9 | 스키마에서도 알 수 있듯, 조금 더 정확히 말하자면 `setState`메소드의 호출은 여러 가지 방법으로, 외부 영향(‘user action’을 의미)이 있을때나 없을때나 실행될 수 있습니다. 두 가지 경우를 생각해 봅시다. 첫 번째는 메서드 호출이 마우스 클릭에 의해 발생되는 경우이고, 두 번째는 `componentDidMount`에서 `setTimeout`이 호출되는 경우입니다. 10 | 11 | 차이점은 무엇일까요? 리엑트는 업데이트를 `batches`로 처리하는데, 그것은 업데이트 목록을 어떻게든 수집하고 `flushed`해야 함을 의미합니다. 마우스 이벤트가 발생되면, 최상위 레벨에서 해당 이벤트가 처리되고, 여러 레이어의 래퍼를 통해 일괄 업데이트가 시작됩니다. 스키마에서 볼 수 있듯이 `ReactEventListener`가 `enabled`(1) 일 때만 발생하는데, 컴포넌트 마운팅 단계에서는, `ReactReconcileTransaction` 래퍼 중 하나가 그 `ReactEventListener`를 비활성화해서, 안전하게 마운팅 할 수 있게 합니다. 그렇다면 `setTimeout case`는 어떨까요? 이것 또한 간단합니다. `dirtyComponents`리스트에 컴포넌트를 넣기 전에, 리엑트는 트랜잭션이 시작(opened)되었는지 확인한 후에 클로즈하고 업데이트를 플러시 해야합니다. 12 | 13 | 아시다시피, 리엑트는 ‘synthetic events’를 구현합니다. 사실 ‘syntax sugar’는 네이트브 이벤트를 래핑하고 있습니다. 그러나 그들은 여전히 우리 모두가 이벤트를 보던 방식대로 행동하려고 합니다. 코드에서 주석을 확인 할 수 있습니다. 14 | > '개발을 돕기 위해 실제 브라우저 이벤트를 시뮬레이트하여 좀 더 나은 통합 개발 도구를 얻을 수 있습니다.' 15 | 16 | ```javascript 17 | var fakeNode = document.createElement('react'); 18 | 19 | ReactErrorUtils.invokeGuardedCallback = function (name, func, a) { 20 | var boundFunc = func.bind(null, a); 21 | var evtType = 'react-' + name; 22 | 23 | fakeNode.addEventListener(evtType, boundFunc, false); 24 | 25 | var evt = document.createEvent('Event'); 26 | evt.initEvent(evtType, false, false); 27 | 28 | fakeNode.dispatchEvent(evt); 29 | fakeNode.removeEventListener(evtType, boundFunc, false); 30 | }; 31 | ``` 32 | 좋습니다. 업데이트를 한번 더 확인해 봅시다. 다음과 같습니다. 33 | 34 | 1. setState 호출 35 | 2. 트랜잭션이 아직 오픈(시작)되지 안았다면, batching 트렌젝션 열기(시작) 36 | 3. `dirtyComponents`리스트에 영향받은 컴포넌트 추가 37 | 4. `ReactUpdates.flushBatchedUpdates`를 호출해서 트랜잭션을 클로즈하고, 실제로 `dirtyComponents`에 수집된 내용을 처리한다는 것을 의미. 38 | 39 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/9/set-state-update-start.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/9/set-state-update-start.svg) 40 | 41 | 9.1 `setState` 시작 (클릭 가능) 42 | 43 | ### 좋습니다, 이제 우리는 *파트 9*를 끝냈습니다. 44 | 45 | 우리가 어떻게 여기까지 왔는지 다시 한번 살펴보도록 합시다. 스키마에서 덜 중요한 부분을 제거하면 다음과 같습니다. 46 | 47 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/9/part-9-A.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/9/part-9-A.svg) 48 | 49 | 9.2 간단히 보는 파트 9 (클릭 가능) 50 | 51 | 공백제거와 정렬을 통해 보기 좋게 수정했습니다. 52 | 53 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/9/part-9-B.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/9/part-9-B.svg) 54 | 55 | 9.3 간단히 보는 파트 9 리펙토링 버전 (클릭 가능) 56 | 57 | 좋습니다. 사실, 이것이 여기서 일어나는 일 전부입니다. 이제 *파트 9*의 핵심들을 가지고 최종 `updating` 스키마에 사용할 수 있습니다. 58 | 59 | [![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/9/part-9-C.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/9/part-9-C.svg) 60 | 61 | 9.6 파트 9의 핵심 (클릭 가능) 62 | 63 | 우리는 해냈습니다! 64 | 65 | 66 | [다음 페이지 : 파트 10 >>](./Part-10.md) 67 | 68 | [<< 이전 페이지 : 파트 8](./Part-8.md) 69 | 70 | 71 | [홈](../../README.md) 72 | -------------------------------------------------------------------------------- /stack/languages/korean/book/README.md: -------------------------------------------------------------------------------- 1 | # Under the hood: ReactJS 2 | 여기에는 리엑트의 내부 작업에 대한 설명을 담았습니다. 전체 코드 기반을 디버깅하면서 모든 로직을 시각적인 블록 스키마에 넣고 분석하고, 주요 개념과 접근 방법을 요약 및 설명했습니다. Stack 버전은 끝났으며, 앞으로는 다음 버전인 Fiber 버전을 작업할 예정입니다. 3 | 4 | >> 더 나은 포맷으로 보고싶으시면 이곳에서 확인하실수 있습니다. : [github-pages website](https://bogdan-lyashenko.github.io/Under-the-hood-ReactJS/) 5 | 6 | > 좋은 아이디어가 있다면, 부담없이 언제든지 issue를 open해주시기 바랍니다. 7 | 8 | 각 스키마는 클릭 가능하고, 새로운 탭에서 열리며, 확대/축소를 하여 보실 수 있습니다. 별도의 창(탭)을 띄워서 아티클과 스키마를 유지시키면, 텍스트와 코드 흐름을 더 쉽게 매칭시키는 데 도움이 될 것입니다. 9 | 10 | 우리는 Stack reconciler가 있는 현재 버전과 다음 버전인 Fiber(아시겠지만, ReactJS의 다음 버전이 곧 공개 될 것입니다.)에 대하여 이야기 할 것입니다. 따라서 당신은 현재의 리엑트가 어떻게 작동하는지 더 잘 이해할 수 있고, Fiber버전에 대한 큰 개선점을 알 수 있을 것입니다. ‘legacy React’가 어떻게 작동되는지 설명하기 위해 [React v15.4.2](https://github.com/facebook/react/tree/v15.4.2)를 사용하며, ‘Fiber’에서는 v16.*.***를 사용합니다. 자 이제, 오래된(이렇게 말하는게 웃깁네요.) 스택 버전부터 시작해보겠습니다. 11 | 12 | 13 | ## Stack reconciler 14 | [![](../../../../stack/images/intro/all-page-stack-reconciler-25-scale.jpg)](./stack/images/intro/all-page-stack-reconciler.svg) 15 | 16 | 전체 스키마는 열다섯개로 나누어져 있습니다. 그럼, 시작하겠습니다. 17 | 18 | * [Intro](../../../../stack/languages/korean/book/Intro.md) 19 | * [Part 0](../../../../stack/languages/korean/book/Part-0.md) 20 | * [Part 1](../../../../stack/languages/korean/book/Part-1.md) 21 | * [Part 2](../../../../stack/languages/korean/book/Part-2.md) 22 | * [Part 3](../../../../stack/languages/korean/book/Part-3.md) 23 | * [Part 4](../../../../stack/languages/korean/book/Part-4.md) 24 | * [Part 5](../../../../stack/languages/korean/book/Part-5.md) 25 | * [Part 6](../../../../stack/languages/korean/book/Part-6.md) 26 | * [Part 7](../../../../stack/languages/korean/book/Part-7.md) 27 | * [Part 8](../../../../stack/languages/korean/book/Part-8.md) 28 | * [Part 9](../../../../stack/languages/korean/book/Part-9.md) 29 | * [Part 10](../../../../stack/languages/korean/book/Part-10.md) 30 | * [Part 11](../../../../stack/languages/korean/book/Part-11.md) 31 | * [Part 12](../../../../stack/languages/korean/book/Part-12.md) 32 | * [Part 13](../../../../stack/languages/korean/book/Part-13.md) 33 | * [Part 14](../../../../stack/languages/korean/book/Part-14.md) 34 | 35 | 36 | 37 | ## Fiber 38 | 1. [Intro](../../../../fiber/book/Intro.md) [TODO] 39 | 40 | 41 | -------------------------------------------------------------------------------- /stack/presentation/css/main.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | height: 100%; 3 | overflow: hidden; 4 | margin: 0; 5 | padding: 0; 6 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; 7 | color: #444; 8 | background-color: rgb(254, 254, 254); 9 | line-height: 1.5; 10 | } 11 | #controls { 12 | position: absolute; 13 | bottom: 0px; 14 | right: 0px; 15 | font-family: sans-serif; 16 | } 17 | 18 | #controls button { 19 | display: inline; 20 | background-color: #272822; 21 | color: #f8f8f2; 22 | border: none; 23 | outline: none; 24 | margin: 0; 25 | font-size: 6pt; 26 | } 27 | 28 | #parent-all-scheme { 29 | height: 100%; 30 | position: relative; 31 | overflow: auto; 32 | padding: 10px; 33 | } 34 | 35 | #img-all-scheme { 36 | position: absolute; 37 | width: 100%; 38 | } 39 | 40 | #parent-part-scheme { 41 | position: absolute; 42 | height: 100%; 43 | width: 100%; 44 | top: 0px; 45 | left: 0px; 46 | overflow: auto; 47 | } 48 | 49 | #img-part-scheme,#img-part-scheme-a,#img-part-scheme-b { 50 | position: absolute; 51 | top: 0px; 52 | left: 0px; 53 | } 54 | 55 | .overlay-piece { 56 | position: absolute; 57 | opacity: 0; 58 | background-color: rgba(39, 40, 34, 0.6); 59 | top: 0px; 60 | left: 0px; 61 | } 62 | 63 | #overlay-border-rect { 64 | position: absolute; 65 | border: 2px solid #272822; 66 | opacity: 0; 67 | } 68 | 69 | #slide-panel { 70 | position: absolute; 71 | top: 0px; 72 | right: 0px; 73 | width: 500px; 74 | height: 100%; 75 | display: none; 76 | opacity: 0; 77 | } 78 | 79 | #slide-header { 80 | padding: 1px; 81 | background-color: #272822; 82 | } 83 | 84 | #slide-content { 85 | border: 1px solid white; 86 | color: #272822; 87 | background-color: rgba(255,255,255, 0.95); 88 | height: 100%; 89 | overflow: auto; 90 | position: relative; 91 | } 92 | 93 | .slide-img-scheme { 94 | top: 10px; 95 | left: 10px; 96 | position: absolute; 97 | } 98 | 99 | #html-block { 100 | position: absolute; 101 | left: 10px; 102 | top: 10px; 103 | } 104 | 105 | .intFactBlock { 106 | font-size: 26pt; 107 | } 108 | 109 | .codeBlock { 110 | width: 100%; 111 | font-size: 20pt; 112 | } 113 | 114 | .textBlock { 115 | font-size: 15pt; 116 | } 117 | 118 | .codeBlockItem { 119 | display: none; 120 | } 121 | 122 | quote { 123 | border-left: 7px solid #ccc; 124 | display: block; 125 | color: #555; 126 | padding-left: 10px; 127 | font-size: 29pt; 128 | } 129 | 130 | #nextAction { 131 | position: absolute; 132 | padding: 10px; 133 | bottom: 20px; 134 | right: 3px; 135 | color: #e0d7d1; 136 | background-color: #5F6364; 137 | border: none; 138 | } 139 | 140 | button { 141 | cursor: pointer; 142 | outline: none; 143 | } -------------------------------------------------------------------------------- /stack/presentation/lib/code-style/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 |
 9 | 		
10 | 			if (tokens instanceof Token) {
11 | 				return new Token(tokens.type, _.util.encode(tokens.content), tokens.alias);
12 | 			} else if (_.util.type(tokens) === 'Array') {
13 | 				return tokens.map(_.util.encode);
14 | 			} else {
15 | 		
16 |
17 | 18 | 19 | 20 | --------------------------------------------------------------------------------