├── .github
└── FUNDING.yml
├── .gitignore
├── LICENSE
├── README.md
├── coding-exercise
├── .gitignore
├── README.md
├── package.json
├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── robots.txt
├── src
│ ├── App.css
│ ├── App.js
│ ├── App.test.js
│ ├── index.css
│ ├── index.js
│ ├── logo.svg
│ ├── serviceWorker.js
│ └── setupTests.js
└── yarn.lock
└── images
├── collab
├── frontendlead-banner.png
├── greatfrontend-banner4x.png
├── uidev-banner2x.png
└── uidev-banner4x.png
├── devtoolsInspect.png
├── devtoolsTab.png
├── error_boundary.png
├── flux.png
├── logo.jpeg
├── phases.png
├── phases16.3.jpg
├── phases16.4.png
├── state.jpg
├── vdom1.png
├── vdom2.png
└── vdom3.png
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: [sudheerj]
4 | custom: https://buymeacoffee.com/sudheerj
5 |
6 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Cruft
2 | .DS_Store
3 | npm-debug.log
4 | .idea
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017-Present Sudheer Jonna
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.
--------------------------------------------------------------------------------
/coding-exercise/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/coding-exercise/README.md:
--------------------------------------------------------------------------------
1 | ### Coding Exercise
2 |
3 | #### 1. What is the output of below code
4 |
5 | ```javascript
6 | import { useState } from 'react';
7 |
8 | export default function Counter() {
9 | const [counter, setCounter] = useState(5);
10 |
11 | return (
12 | <>
13 | {counter}
14 |
21 | >
22 | )
23 | }
24 | ```
25 |
26 | - 1: Alert with 5, 5
27 | - 2: Alert with 15, 25
28 | - 3: Alert with 5, 10
29 | - 4: Error: Cannot update the same state multiple times concurrently
30 |
31 | Answer
32 |
33 |
34 | ##### Answer: 3
35 | State values are fixed(i.e, default value 5) in each render and setting the state only changes it for the next render. React will wait until all the code executed with in an event handler before your state updates followed by re-rendering the UI. Also, all the 3 setter function calls are replacing the calculated value. Hence, irrespective of how many times you call `setCounter(counter + 5)` the final value is 10(5+5).
36 |
37 | This can be visuallized by substituting with state variable values in the particular render,
38 | ```javascript
39 |
46 | ```
47 |
84 |
85 | ##### Answer: 1
86 |
87 | React queues all the updater functions(e.g, counter => counter + 5) which will be processed after all the code inside event handler has been executed. During the next re-render(state update through setState), React goes through the queue and increment the counter based on the previous value in each function call. So the final value of counter becomes 25(initial value 5 + 5 + 5 + 5 + 5) whereas the alert shows default value 5 because the counter value won't be updated by that time.
88 |
89 |
90 |
91 |
92 | ---
93 |
94 | **[⬆ Back to Top](#table-of-contents)**
95 |
96 | #### 3. What is the output of span after one click?
97 |
98 | ```javascript
99 | import { useRef } from 'react';
100 |
101 | export default function Counter() {
102 | let countRef = useRef(0);
103 |
104 | function handleIncrement() {
105 | countRef.current = countRef.current + 1;
106 | }
107 |
108 | return
109 | <>
110 | Count: {countRef.current}
111 |
114 | >
115 | }
116 | ```
117 |
118 | - 1: Cannot read current property of undefined
119 | - 2: Count: 1
120 | - 3: null
121 | - 4: Count: 0
122 |
123 | Answer
124 |
125 |
126 | ##### Answer: 4
127 |
128 | In React, every update has two phases.
129 | 1. **Render:** This is where React calls the components in order to output something on the screen
130 | 2. **Commit:** React applies changes to the DOM
131 |
132 | Any updates to the ref will be reflected only in the commit phase. In other words, React sets **counterRef.current** during the commit phase. Hence, **countRef.current** always holds value `0` irrespective of how many times the Increment button clicked.
133 |
134 |
135 |
136 | ---
137 |
138 | **[⬆ Back to Top](#table-of-contents)**
139 |
140 | #### 4. What is the outcome of below code after button click?
141 |
142 | ```javascript
143 | import { useRef } from 'react';
144 |
145 | function MyCustomInput(props) {
146 | return ;
147 | }
148 |
149 | export default function MyCustomForm() {
150 | const inputRef = useRef(null);
151 |
152 | function handleInputFocus() {
153 | inputRef.current.focus();
154 | }
155 |
156 | return (
157 | <>
158 |
159 |
162 | >
163 | );
164 | }
165 | ```
166 |
167 | - 1: Input gets the focus
168 | - 2: Warning: Function components cannot be given refs.
169 | - 3: Cannot read current property of undefined
170 | - 4: Warning: Missing ref on element
171 |
172 | Answer
173 |
174 |
175 | ##### Answer: 2
176 | By default, React does not allow a component access the DOM nodes of other components even for child components. If you still try to access the DOM nodes directly then you will receive below error:
177 |
178 | ```javascript
179 | Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
180 | ```
181 |
182 | This issue can be fixed by wrapping the **** component with `forwardRef` function which accepts ref as the second argument which can be used on the **** element as **ref={ref}**
183 |
184 |
185 |
186 |
187 | ---
188 |
189 | **[⬆ Back to Top](#table-of-contents)**
190 |
191 | #### 5. What is the outcome of number of clicks after 3 button clicks?
192 |
193 | ```javascript
194 | import { useRef } from 'react';
195 |
196 | export default function Counter() {
197 | let ref = useRef(0);
198 |
199 | function handleClick() {
200 | ref.current = ref.current + 1;
201 | }
202 |
203 | return (
204 | <>
205 |
221 |
222 | ##### Answer: 4
223 | If you try to use **{ref.current}** in the render method, the number won’t be updated on click. This is because **ref.current** does not trigger a re-render unlike state. This property is mainly used to read and write the values inside event handler or outside the render method.
224 |