├── .vscode
├── launch.json
└── settings.json
├── README.md
├── _config.yml
├── assets
├── Higher-Order-Components.jpg
├── component-tree.png
├── context-api.jpg
├── dom.png
├── flux-2.png
├── flux-architecture.png
├── flux-structure.png
├── flux.png
├── mvc.png
├── poketimes-project.png
├── props-state.jpg
├── react-architecture.png
├── react-dev-tools.png
├── react-features.png
├── react-fiber.png
├── react-form.png
├── react-hooks.png
├── react-lifecycle.png
├── react-native-architecture.jpg
├── react-redux-form.png
├── react-redux.png
├── react-roadmap.png
├── react-routing.png
├── react-sight.png
├── react-store.png
├── react-twoway-data-binding.png
├── reconciliation.jpg
├── redux-2.png
├── redux-and-flux.png
├── redux-architecture.png
├── redux-components.jpg
├── redux-cycle.png
├── redux-data-flow.gif
├── redux-saga.png
├── redux-state.png
├── redux-thunk.jpeg
├── redux-workflow.png
├── redux.png
├── shadow-dom.png
├── star.png
├── todo-project.png
├── useLayoutEffect.png
└── virtualdom-vs-realdom.png
├── best-practices.md
├── jest-quick-reference.md
├── react-quick-reference.md
└── redux-quick-reference.md
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "type": "chrome",
9 | "request": "launch",
10 | "name": "Launch Chrome against localhost",
11 | "url": "http://localhost:8080",
12 | "webRoot": "${workspaceFolder}"
13 | }
14 | ]
15 | }
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "git.ignoreLimitWarning": true
3 | }
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-cayman
--------------------------------------------------------------------------------
/assets/Higher-Order-Components.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/Higher-Order-Components.jpg
--------------------------------------------------------------------------------
/assets/component-tree.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/component-tree.png
--------------------------------------------------------------------------------
/assets/context-api.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/context-api.jpg
--------------------------------------------------------------------------------
/assets/dom.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/dom.png
--------------------------------------------------------------------------------
/assets/flux-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/flux-2.png
--------------------------------------------------------------------------------
/assets/flux-architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/flux-architecture.png
--------------------------------------------------------------------------------
/assets/flux-structure.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/flux-structure.png
--------------------------------------------------------------------------------
/assets/flux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/flux.png
--------------------------------------------------------------------------------
/assets/mvc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/mvc.png
--------------------------------------------------------------------------------
/assets/poketimes-project.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/poketimes-project.png
--------------------------------------------------------------------------------
/assets/props-state.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/props-state.jpg
--------------------------------------------------------------------------------
/assets/react-architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/react-architecture.png
--------------------------------------------------------------------------------
/assets/react-dev-tools.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/react-dev-tools.png
--------------------------------------------------------------------------------
/assets/react-features.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/react-features.png
--------------------------------------------------------------------------------
/assets/react-fiber.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/react-fiber.png
--------------------------------------------------------------------------------
/assets/react-form.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/react-form.png
--------------------------------------------------------------------------------
/assets/react-hooks.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/react-hooks.png
--------------------------------------------------------------------------------
/assets/react-lifecycle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/react-lifecycle.png
--------------------------------------------------------------------------------
/assets/react-native-architecture.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/react-native-architecture.jpg
--------------------------------------------------------------------------------
/assets/react-redux-form.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/react-redux-form.png
--------------------------------------------------------------------------------
/assets/react-redux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/react-redux.png
--------------------------------------------------------------------------------
/assets/react-roadmap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/react-roadmap.png
--------------------------------------------------------------------------------
/assets/react-routing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/react-routing.png
--------------------------------------------------------------------------------
/assets/react-sight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/react-sight.png
--------------------------------------------------------------------------------
/assets/react-store.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/react-store.png
--------------------------------------------------------------------------------
/assets/react-twoway-data-binding.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/react-twoway-data-binding.png
--------------------------------------------------------------------------------
/assets/reconciliation.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/reconciliation.jpg
--------------------------------------------------------------------------------
/assets/redux-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/redux-2.png
--------------------------------------------------------------------------------
/assets/redux-and-flux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/redux-and-flux.png
--------------------------------------------------------------------------------
/assets/redux-architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/redux-architecture.png
--------------------------------------------------------------------------------
/assets/redux-components.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/redux-components.jpg
--------------------------------------------------------------------------------
/assets/redux-cycle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/redux-cycle.png
--------------------------------------------------------------------------------
/assets/redux-data-flow.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/redux-data-flow.gif
--------------------------------------------------------------------------------
/assets/redux-saga.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/redux-saga.png
--------------------------------------------------------------------------------
/assets/redux-state.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/redux-state.png
--------------------------------------------------------------------------------
/assets/redux-thunk.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/redux-thunk.jpeg
--------------------------------------------------------------------------------
/assets/redux-workflow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/redux-workflow.png
--------------------------------------------------------------------------------
/assets/redux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/redux.png
--------------------------------------------------------------------------------
/assets/shadow-dom.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/shadow-dom.png
--------------------------------------------------------------------------------
/assets/star.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/star.png
--------------------------------------------------------------------------------
/assets/todo-project.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/todo-project.png
--------------------------------------------------------------------------------
/assets/useLayoutEffect.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/useLayoutEffect.png
--------------------------------------------------------------------------------
/assets/virtualdom-vs-realdom.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krishnakiriti04/react-interview-questions/b19d5a7a3e90272ec9bbc6b89f08b079dbaec111/assets/virtualdom-vs-realdom.png
--------------------------------------------------------------------------------
/best-practices.md:
--------------------------------------------------------------------------------
1 | # React Best Practices
2 |
3 | 1. Component name must start with capitals letters.
4 |
5 | 2. All the component must be small and function-specific.
6 |
7 | 3. All the component must have small description
8 |
9 | ```js
10 | /**
11 | *
12 | * Author: {...}
13 | * Description: {...}
14 | * Dependencies: {...}
15 | *
16 | **/
17 | const SampleComponent = () => {
18 |
19 | return (
20 |
21 | Sample Component !
22 |
23 | );
24 | }
25 |
26 | export default SampleComponent;
27 | ```
28 |
29 | 4. All code must follow es6 coding standards.
30 |
31 | 5. For variables that are NOT constants or constructors, multi-word variables and functions SHOULD be lowerCamelCased.
32 |
33 | 6. Constants:- Pre-defined constants SHOULD be all-uppercase, and words separated by underscores: UPPER_UNDERSCORED.
34 |
35 | 7. Typeof:- In type comparisons, the value tested MUST NOT be wrapped in parenthesis and use triple equals to.
36 |
37 | ```js
38 | if (typeof myVariable === 'string') {
39 | // ...
40 | }
41 | ```
42 |
43 | 8. In simple condition, Ternary operator should be used instead of if else statement.
44 |
45 | ```js
46 | // If-else Statement
47 | if(condition) {
48 | //...
49 | } else {
50 | //...
51 | }
52 |
53 | // Ternary operator
54 | let myVariable = condition ? exprIfTrue : exprIfFalse
55 | ```
56 |
57 | 9. fragments should be used instead of container div.
58 |
59 | ```js
60 | ...
61 |
62 | render() {
63 | return (
64 |
65 | Some text.
66 | A heading
67 | More text.
68 | Another heading
69 | Even more text.
70 |
71 | );
72 | }
73 | ```
74 |
75 | 10. All files related to any one component should be in a single folder
76 |
77 | 11. Functional components should be favored if we do not need to make use of React state.
78 |
79 | 12. Anonymous functions should not be used as handlers.
80 |
81 | 13. Inline styles should not be used inside component.
82 |
83 | 14. For a component to hide itself return null from render.
84 |
85 | 15. Higher Order Components should be used for cross-cutting concerns.
86 |
87 | 16. Prefer state initialization in class member variable declaration over constructor
88 |
89 | 17. Index should not be used as a key
90 |
91 | 18. Short-Circuit evaluation should be used in jsx
92 |
93 | ```js
94 | // Avoid
95 | const sampleComponent = () => {
96 | return isTrue ? True!
: null
97 | };
98 |
99 | // Recommended: short-circuit evaluation
100 | const sampleComponent = () => {
101 | return isTrue && True!
102 | };
103 | ```
104 |
--------------------------------------------------------------------------------
/jest-quick-reference.md:
--------------------------------------------------------------------------------
1 | # Jest Quick Reference
2 |
3 | - [Test structure](#test-structure)
4 | - [Matchers](#matchers)
5 | - [Basic matchers](#basic-matchers)
6 | - [Truthiness](#truthiness)
7 | - [Numbers](#numbers)
8 | - [Strings](#strings)
9 | - [Arrays](#arrays)
10 | - [Objects](#objects)
11 | - [Exceptions](#exceptions)
12 | - [Snapshots](#snapshots)
13 | - [Mock functions](#mock-functions)
14 | - [Misc](#misc)
15 | - [Promise matchers (Jest 20+)](#promise-matchers-jest-20)
16 | - [Async tests](#async-tests)
17 | - [async/await](#asyncawait)
18 | - [Promises](#promises)
19 | - [done() callback](#done-callback)
20 | - [Mocks](#mocks)
21 | - [Mock functions](#mock-functions-1)
22 | - [Returning, resolving and rejecting values](#Returning-resolving-and-rejecting-values)
23 | - [Mock modules using `jest.mock` method](#mock-modules-using-jestmock-method)
24 | - [Mock modules using a mock file](#mock-modules-using-a-mock-file)
25 | - [Mock object methods](#mock-object-methods)
26 | - [Mock getters and setters (Jest 22.1.0+)](#mock-getters-and-setters-jest-2210)
27 | - [Mock getters and setters](#mock-getters-and-setters)
28 | - [Clearing and restoring mocks](#clearing-and-restoring-mocks)
29 | - [Accessing the original module when using mocks](#accessing-the-original-module-when-using-mocks)
30 | - [Timer mocks](#timer-mocks)
31 | - [Data-driven tests (Jest 23+)](#data-driven-tests-jest-23)
32 | - [Skipping tests](#skipping-tests)
33 | - [Testing modules with side effects](#testing-modules-with-side-effects)
34 |
35 | ## Basic Test Structure
36 |
37 | ```js
38 | describe('Color Picker', () => {
39 | beforeAll(() => {
40 | /* Runs before all tests */
41 | })
42 | afterAll(() => {
43 | /* Runs after all tests */
44 | })
45 | beforeEach(() => {
46 | /* Runs before each test */
47 | })
48 | afterEach(() => {
49 | /* Runs after each test */
50 | })
51 |
52 | test('Choose a color', () => {
53 | const actual = fn(['Alice', 'Bob', 'Eve'])
54 | expect(actual).toEqual(['Pink Alice', 'Pink Bob', 'Pink Eve'])
55 | })
56 | })
57 | ```
58 |
59 | ## Matchers
60 |
61 | [Using matchers](http://jestjs.io/docs/en/using-matchers), [matchers docs](https://facebook.github.io/jest/docs/expect.html)
62 |
63 | ### Basic matchers
64 |
65 | ```js
66 | expect(42).toBe(42) // Strict equality (===)
67 | expect(42).not.toBe(3) // Strict equality (!==)
68 | expect([1, 2]).toEqual([1, 2]) // Deep equality
69 | expect({ a: undefined, b: 2 }).toEqual({ b: 2 }) // Deep equality
70 | expect({ a: undefined, b: 2 }).not.toStrictEqual({ b: 2 }) // Strict equality (Jest 23+)
71 | ```
72 |
73 | ### Truthiness
74 |
75 | ```js
76 | // Matches anything that an if statement treats as true (not false, 0, '', null, undefined, NaN)
77 | expect('foo').toBeTruthy()
78 | // Matches anything that an if statement treats as false (false, 0, '', null, undefined, NaN)
79 | expect('').toBeFalsy()
80 | // Matches only null
81 | expect(null).toBeNull()
82 | // Matches only undefined
83 | expect(undefined).toBeUndefined()
84 | // The opposite of toBeUndefined
85 | expect(7).toBeDefined()
86 | // Matches true or false
87 | expect(true).toEqual(expect.any(Boolean))
88 | ```
89 |
90 | ### Numbers
91 |
92 | ```js
93 | expect(2).toBeGreaterThan(1)
94 | expect(1).toBeGreaterThanOrEqual(1)
95 | expect(1).toBeLessThan(2)
96 | expect(1).toBeLessThanOrEqual(1)
97 | expect(0.2 + 0.1).toBeCloseTo(0.3, 5)
98 | expect(NaN).toEqual(expect.any(Number))
99 | ```
100 |
101 | ### Strings
102 |
103 | ```js
104 | expect('long string').toMatch('str')
105 | expect('string').toEqual(expect.any(String))
106 | expect('coffee').toMatch(/ff/)
107 | expect('pizza').not.toMatch('coffee')
108 | expect(['pizza', 'coffee']).toEqual([expect.stringContaining('zz'), expect.stringMatching(/ff/)])
109 | ```
110 |
111 | ### Arrays
112 |
113 | ```js
114 | expect([]).toEqual(expect.any(Array))
115 | expect(['Alice', 'Bob', 'Eve']).toHaveLength(3)
116 | expect(['Alice', 'Bob', 'Eve']).toContain('Alice')
117 | expect([{ a: 1 }, { a: 2 }]).toContainEqual({ a: 1 })
118 | expect(['Alice', 'Bob', 'Eve']).toEqual(expect.arrayContaining(['Alice', 'Bob']))
119 | ```
120 |
121 | ### Objects
122 |
123 | ```js
124 | expect({ a: 1 }).toHaveProperty('a')
125 | expect({ a: 1 }).toHaveProperty('a', 1)
126 | expect({ a: { b: 1 } }).toHaveProperty('a.b')
127 | expect({ a: 1, b: 2 }).toMatchObject({ a: 1 })
128 | expect({ a: 1, b: 2 }).toMatchObject({
129 | a: expect.any(Number),
130 | b: expect.any(Number)
131 | })
132 | expect([{ a: 1 }, { b: 2 }]).toEqual([
133 | expect.objectContaining({ a: expect.any(Number) }),
134 | expect.anything()
135 | ])
136 | ```
137 |
138 | ### Exceptions
139 |
140 | ```js
141 | // const fn = () => { throw new Error('Out of cheese!') }
142 | expect(fn).toThrow()
143 | expect(fn).toThrow('Out of cheese')
144 | expect(fn).toThrowErrorMatchingSnapshot()
145 | ```
146 |
147 | ### Snapshots
148 |
149 | ```js
150 | expect(node).toMatchSnapshot()
151 | // Jest 23+
152 | expect(user).toMatchSnapshot({
153 | date: expect.any(Date)
154 | })
155 | expect(user).toMatchInlineSnapshot()
156 | ```
157 |
158 | ### Mock functions
159 |
160 | ```js
161 | // const fn = jest.fn()
162 | // const fn = jest.fn().mockName('Unicorn') -- named mock, Jest 22+
163 | expect(fn).toBeCalled() // Function was called
164 | expect(fn).not.toBeCalled() // Function was *not* called
165 | expect(fn).toHaveBeenCalledTimes(1) // Function was called only once
166 | expect(fn).toBeCalledWith(arg1, arg2) // Any of calls was with these arguments
167 | expect(fn).toHaveBeenLastCalledWith(arg1, arg2) // Last call was with these arguments
168 | expect(fn).toHaveBeenNthCalledWith(args) // Nth call was with these arguments (Jest 23+)
169 | expect(fn).toHaveReturnedTimes(2) // Function was returned without throwing an error (Jest 23+)
170 | expect(fn).toHaveReturnedWith(value) // Function returned a value (Jest 23+)
171 | expect(fn).toHaveLastReturnedWith(value) // Last function call returned a value (Jest 23+)
172 | expect(fn).toHaveNthReturnedWith(value) // Nth function call returned a value (Jest 23+)
173 | expect(fn.mock.calls).toEqual([['first', 'call', 'args'], ['second', 'call', 'args']]) // Multiple calls
174 | expect(fn.mock.calls[0][0]).toBe(2) // fn.mock.calls[0][0] — the first argument of the first call
175 | ```
176 |
177 |
178 | Aliases
179 |
180 | - `toBeCalled` → `toHaveBeenCalled`
181 | - `toBeCalledWith` → `toHaveBeenCalledWith`
182 | - `lastCalledWith` → `toHaveBeenLastCalledWith`
183 | - `nthCalledWith` → `toHaveBeenNthCalledWith`
184 | - `toReturnTimes` → `toHaveReturnedTimes`
185 | - `toReturnWith` → `toHaveReturnedWith`
186 | - `lastReturnedWith` → `toHaveLastReturnedWith`
187 | - `nthReturnedWith` → `toHaveNthReturnedWith`
188 |
189 |
190 | ### Misc
191 |
192 | ```js
193 | expect(new A()).toBeInstanceOf(A)
194 | expect(() => {}).toEqual(expect.any(Function))
195 | expect('pizza').toEqual(expect.anything())
196 | ```
197 |
198 | ### Promise matchers (Jest 20+)
199 |
200 | ```js
201 | test('resolve to lemon', () => {
202 | expect.assertions(1)
203 | // Make sure to add a return statement
204 | return expect(Promise.resolve('lemon')).resolves.toBe('lemon')
205 | return expect(Promise.reject('octopus')).rejects.toBeDefined()
206 | return expect(Promise.reject(Error('pizza'))).rejects.toThrow()
207 | })
208 | ```
209 |
210 | Or with async/await:
211 |
212 | ```js
213 | test('resolve to lemon', async () => {
214 | expect.assertions(2)
215 | await expect(Promise.resolve('lemon')).resolves.toBe('lemon')
216 | await expect(Promise.resolve('lemon')).resolves.not.toBe('octopus')
217 | })
218 | ```
219 |
220 | [resolves docs](https://facebook.github.io/jest/docs/en/expect.html#resolves)
221 |
222 | ## Async tests
223 |
224 | See [more examples](https://facebook.github.io/jest/docs/en/tutorial-async.html) in Jest docs.
225 |
226 | It’s a good practice to specify a number of expected assertions in async tests, so the test will fail if your assertions weren’t called at all.
227 |
228 | ```js
229 | test('async test', () => {
230 | expect.assertions(3) // Exactly three assertions are called during a test
231 | // OR
232 | expect.hasAssertions() // At least one assertion is called during a test
233 |
234 | // Your async tests
235 | })
236 | ```
237 | Note that you can also do this per file, outside any `describe` and `test`:
238 | ```js
239 | beforeEach(expect.hasAssertions)
240 | ```
241 | This will verify the presense of at least one assertion per test case. It also plays nice with more specific `expect.assertions(3)` declarations.
242 |
243 | ### async/await
244 |
245 | ```js
246 | test('async test', async () => {
247 | expect.assertions(1)
248 | const result = await runAsyncOperation()
249 | expect(result).toBe(true)
250 | })
251 | ```
252 |
253 | ### Promises
254 |
255 | _Return_ a Promise from your test:
256 |
257 | ```js
258 | test('async test', () => {
259 | expect.assertions(1)
260 | return runAsyncOperation().then(result => {
261 | expect(result).toBe(true)
262 | })
263 | })
264 | ```
265 |
266 | ### done() callback
267 |
268 | Wrap your assertions in try/catch block, otherwise Jest will ignore failures:
269 |
270 | ```js
271 | test('async test', done => {
272 | expect.assertions(1)
273 | runAsyncOperation()
274 | setTimeout(() => {
275 | try {
276 | const result = getAsyncOperationResult()
277 | expect(result).toBe(true)
278 | done()
279 | } catch (err) {
280 | done.fail(err)
281 | }
282 | })
283 | })
284 | ```
285 |
286 | ## Mocks
287 |
288 | ### Mock functions
289 |
290 | ```js
291 | test('call the callback', () => {
292 | const callback = jest.fn()
293 | fn(callback)
294 | expect(callback).toBeCalled()
295 | expect(callback.mock.calls[0][1].baz).toBe('pizza') // Second argument of the first call
296 | // Match the first and the last arguments but ignore the second argument
297 | expect(callback).toHaveBeenLastCalledWith('meal', expect.anything(), 'margarita');
298 | })
299 | ```
300 |
301 | You can also use snapshots:
302 |
303 | ```js
304 | test('call the callback', () => {
305 | const callback = jest.fn().mockName('Unicorn') // mockName is available in Jest 22+
306 | fn(callback)
307 | expect(callback).toMatchSnapshot()
308 | // ->
309 | // [MockFunction Unicorn] {
310 | // "calls": Array [
311 | // ...
312 | })
313 | ```
314 |
315 | And pass an implementation to `jest.fn` function:
316 |
317 | ```js
318 | const callback = jest.fn(() => true)
319 | ```
320 |
321 | [Mock functions docs](https://facebook.github.io/jest/docs/mock-function-api.html)
322 |
323 | ### Returning, resolving and rejecting values
324 |
325 | Your mocks can return values:
326 |
327 | ```js
328 | const callback = jest.fn().mockReturnValue(true);
329 | const callbackOnce = jest.fn().mockReturnValueOnce(true);
330 | ```
331 |
332 | Or resolve values:
333 |
334 | ```js
335 | const promise = jest.fn().mockResolvedValue(true);
336 | const promiseOnce = jest.fn().mockResolvedValueOnce(true);
337 | ```
338 |
339 | They can even reject values:
340 |
341 | ```js
342 | const failedPromise = jest.fn().mockRejectedValue("Error");
343 | const failedPromiseOnce = jest.fn().mockRejectedValueOnce("Error");
344 | ```
345 |
346 | You can even combine these:
347 |
348 | ```js
349 | const callback = jest.fn()
350 | .mockReturnValueOnce(false)
351 | .mockReturnValue(true);
352 |
353 | // ->
354 | // call 1: false
355 | // call 2+: true
356 | ```
357 |
358 | ### Mock modules using `jest.mock` method
359 |
360 | ```js
361 | jest.mock('lodash/memoize', () => a => a) // The original lodash/memoize should exist
362 | jest.mock('lodash/memoize', () => a => a, { virtual: true }) // The original lodash/memoize isn’t required
363 | ```
364 |
365 | [jest.mock docs](https://facebook.github.io/jest/docs/jest-object.html#jestmockmodulename-factory-options)
366 |
367 | > Note: When using `babel-jest`, calls to `jest.mock` will automatically be hoisted to the top of the code block. Use `jest.doMock` if you want to explicitly avoid this behavior.
368 |
369 | ### Mock modules using a mock file
370 |
371 | 1. Create a file like `__mocks__/lodash/memoize.js`:
372 |
373 | ```js
374 | module.exports = a => a
375 | ```
376 |
377 | 2. Add to your test:
378 |
379 | ```js
380 | jest.mock('lodash/memoize')
381 | ```
382 |
383 | > Note: When using `babel-jest`, calls to `jest.mock` will automatically be hoisted to the top of the code block. Use `jest.doMock` if you want to explicitly avoid this behavior.
384 |
385 | [Manual mocks docs](https://facebook.github.io/jest/docs/manual-mocks.html)
386 |
387 | ### Mock object methods
388 |
389 | ```js
390 | const spy = jest.spyOn(console, 'log').mockImplementation(() => {})
391 | expect(console.log.mock.calls).toEqual([['dope'], ['nope']])
392 | spy.mockRestore()
393 | ```
394 |
395 | ```js
396 | const spy = jest.spyOn(ajax, 'request').mockImplementation(() => Promise.resolve({ success: true }))
397 | expect(spy).toHaveBeenCalled()
398 | spy.mockRestore()
399 | ```
400 |
401 | ### Mock getters and setters (Jest 22.1.0+)
402 |
403 | ```js
404 | const location = {}
405 | const getTitle = jest.spyOn(location, 'title', 'get').mockImplementation(() => 'pizza')
406 | const setTitle = jest.spyOn(location, 'title', 'set').mockImplementation(() => {})
407 | ```
408 |
409 | ### Mock getters and setters
410 |
411 | ```js
412 | const getTitle = jest.fn(() => 'pizza')
413 | const setTitle = jest.fn()
414 | const location = {}
415 | Object.defineProperty(location, 'title', {
416 | get: getTitle,
417 | set: setTitle
418 | })
419 | ```
420 |
421 | ### Clearing and restoring mocks
422 |
423 | For one mock:
424 |
425 | ```js
426 | fn.mockClear() // Clears mock usage date (fn.mock.calls, fn.mock.instances)
427 | fn.mockReset() // Clears and removes any mocked return values or implementations
428 | fn.mockRestore() // Resets and restores the initial implementation
429 | ```
430 |
431 | > Note: `mockRestore` works only with mocks created by `jest.spyOn`.
432 |
433 | For all mocks:
434 |
435 | ```js
436 | jest.clearAllMocks()
437 | jest.resetAllMocks()
438 | jest.restoreAllMocks()
439 | ```
440 |
441 | ### Accessing the original module when using mocks
442 |
443 | ```js
444 | jest.mock('fs')
445 | const fs = require('fs') // Mocked module
446 | const fs = require.requireActual('fs') // Original module
447 | ```
448 |
449 | ### Timer mocks
450 |
451 | Write synchronous test for code that uses native timer functions (`setTimeout`, `setInterval`, `clearTimeout`, `clearInterval`).
452 |
453 | ```js
454 | // Enable fake timers
455 | jest.useFakeTimers()
456 |
457 | test('kill the time', () => {
458 | const callback = jest.fn()
459 |
460 | // Run some code that uses setTimeout or setInterval
461 | const actual = someFunctionThatUseTimers(callback)
462 |
463 | // Fast-forward until all timers have been executed
464 | jest.runAllTimers()
465 |
466 | // Check the results synchronously
467 | expect(callback).toHaveBeenCalledTimes(1)
468 | })
469 | ```
470 |
471 | Or adjust timers by time with [advanceTimersByTime()](https://jestjs.io/docs/en/timer-mocks#advance-timers-by-time):
472 |
473 | ```js
474 | // Enable fake timers
475 | jest.useFakeTimers()
476 |
477 | test('kill the time', () => {
478 | const callback = jest.fn()
479 |
480 | // Run some code that uses setTimeout or setInterval
481 | const actual = someFunctionThatUseTimers(callback)
482 |
483 | // Fast-forward for 250 ms
484 | jest.advanceTimersByTime(250)
485 |
486 | // Check the results synchronously
487 | expect(callback).toHaveBeenCalledTimes(1)
488 | })
489 | ```
490 |
491 | Use [jest.runOnlyPendingTimers()](https://jestjs.io/docs/en/timer-mocks#run-pending-timers) for special cases.
492 |
493 | **Note:** you should call `jest.useFakeTimers()` in your test case to use other fake timer methods.
494 |
495 | ## Data-driven tests (Jest 23+)
496 |
497 | Run the same test with different data:
498 |
499 | ```js
500 | test.each([[1, 1, 2], [1, 2, 3], [2, 1, 3]])('.add(%s, %s)', (a, b, expected) => {
501 | expect(a + b).toBe(expected)
502 | })
503 | ```
504 |
505 | Or the same using template literals:
506 |
507 | ```js
508 | test.each`
509 | a | b | expected
510 | ${1} | ${1} | ${2}
511 | ${1} | ${2} | ${3}
512 | ${2} | ${1} | ${3}
513 | `('returns $expected when $a is added $b', ({ a, b, expected }) => {
514 | expect(a + b).toBe(expected)
515 | })
516 | ```
517 |
518 | Or on `describe` level:
519 |
520 | ```js
521 | describe.each([['mobile'], ['tablet'], ['desktop']])('checkout flow on %s', (viewport) => {
522 | test('displays success page', () => {
523 | //
524 | })
525 | })
526 | ```
527 |
528 | [describe.each() docs](https://jestjs.io/docs/en/api.html#describeeachtablename-fn-timeout), [test.each() docs](https://jestjs.io/docs/en/api.html#testeachtablename-fn-timeout),
529 |
530 | ## Skipping tests
531 |
532 | Do not run these tests:
533 |
534 | ```js
535 | describe.skip('makePoniesPink'...
536 | tests.skip('make each pony pink'...
537 | ```
538 |
539 | Run only these tests:
540 |
541 | ```js
542 | describe.only('makePoniesPink'...
543 | tests.only('make each pony pink'...
544 | ```
545 |
546 | ## Testing modules with side effects
547 |
548 | Node.js and Jest will cache modules you `require`. To test modules with side effects you’ll need to reset the module registry between tests:
549 |
550 | ```js
551 | const modulePath = '../module-to-test'
552 |
553 | afterEach(() => {
554 | jest.resetModules()
555 | })
556 |
557 | test('first test', () => {
558 | // Prepare conditions for the first test
559 | const result = require(modulePath)
560 | expect(result).toMatchSnapshot()
561 | })
562 |
563 | test('second text', () => {
564 | // Prepare conditions for the second test
565 | const fn = () => require(modulePath)
566 | expect(fn).toThrow()
567 | })
568 | ```
569 |
--------------------------------------------------------------------------------
/react-quick-reference.md:
--------------------------------------------------------------------------------
1 | # React Quick Reference
2 |
3 | - Components
4 | - [Components](#components)
5 | - [Stateless Components](#stateless-components)
6 | - [Functional Components](#functional-components)
7 | - [Pure Components](#pure-components)
8 | - Properties
9 | - [Props](#properties)
10 | - [States](#states)
11 | - [Children](#children)
12 | - [Nesting](#nesting)
13 | - [Transferring props](#transferring-props)
14 | - [Portals](#portals)
15 | - [Hydration](#hydration)
16 | - [PropTypes](#proptypes)
17 | - [Basic types](#basic-types)
18 | - [Required Types](#required-types)
19 | - [Elements](#elements)
20 | - [Enumerables](#enumerables)
21 | - [Custom validation](#custom-validation)
22 | - [Arrays and Objects](#arrays-and-objects)
23 | - Lifecycle
24 | - [Mounting](#mounting)
25 | - [Updating](#updating)
26 | - [Errors](#errors)
27 | - Hooks
28 | - [State Hook](#state-hook)
29 | - [Effect Hook](#effect-hook)
30 | - [References](#references)
31 | - [DOM Events](#dom-events)
32 | - JSX patterns
33 | - [Style shorthand](#style-shorthand)
34 | - [Conditionals](#conditionals)
35 | - [Lists](#lists)
36 | - [Short-Circuit Evaluation](#short-circuit-evaluation)
37 | - [Fragments and Arrays](#fragments-and-arrays)
38 |
39 | ## Components
40 |
41 | ```javascript
42 | import React from 'react';
43 | import ReactDOM from 'react-dom';
44 |
45 | class Hello extends React.Component {
46 | render () {
47 | return (
48 |
49 | Hello {this.props.name}
50 |
51 | )
52 | }
53 | }
54 | const el = document.body
55 | ReactDOM.render( , el)
56 | ```
57 |
58 | ## Stateless Components
59 |
60 | ```javascript
61 | // Stateless React Component
62 | const Headline = () => {
63 | return React Quick Reference
64 | }
65 |
66 | // Component that receives props
67 | const Greetings = (props) => {
68 | return You will love it {props.name}.
69 | }
70 |
71 | // Component must only return ONE element (eg. DIV)
72 | const Intro = () => {
73 | return (
74 |
75 |
76 |
Welcome to the React world!
77 |
78 |
79 | )
80 | }
81 |
82 | ReactDOM.render(
83 | ,
84 | document.getElementById('root')
85 | );
86 | ```
87 |
88 | ## Properties
89 |
90 | ```javascript
91 |
92 |
93 | render () {
94 | this.props.fullscreen;
95 |
96 | // Use `this.props` to access properties passed to the component.
97 | const { fullscreen, autoplay } = this.props;
98 | }
99 | ```
100 |
101 | ## States
102 |
103 | ```javascript
104 | constructor(props) {
105 | super(props)
106 | this.state = { username: undefined }
107 | }
108 |
109 | this.setState({ username: 'Alex' })
110 |
111 | render () {
112 | this.state.username;
113 |
114 | // Use states `this.state` to manage dynamic data.
115 | const { username } = this.state
116 | }
117 | ```
118 |
119 | ## Children
120 |
121 | ```javascript
122 |
123 | You have pending notifications
124 |
125 |
126 | class AlertBox extends Component {
127 | render () {
128 | return (
129 |
130 | // Children are passed as the children property.
131 |
132 | {this.props.children}
133 |
134 | )
135 | }
136 | }
137 | ```
138 |
139 | ## Nesting
140 |
141 | ```javascript
142 | import React, { Component, Fragment } from 'react';
143 |
144 | class Info extends Component {
145 | render () {
146 | const { avatar, username } = this.props
147 |
148 | return (
149 |
150 |
151 |
152 |
153 | )
154 | }
155 | }
156 | ```
157 |
158 | ## Functional components
159 |
160 | Functional components have no state. Also, their props are passed as the first parameter to a function.
161 |
162 | ```javascript
163 | function MyComponent ({ name }) {
164 |
165 | return (
166 |
167 | Hello {name}
168 |
169 | )
170 | }
171 | ```
172 |
173 | ## Pure Components
174 |
175 | Performance-optimized version of React.Component.
176 |
177 | ```javascript
178 | import React, { PureComponent } from 'react';
179 |
180 | class MessageBox extends PureComponent {
181 | ···
182 | }
183 | ```
184 |
185 | ## Mounting
186 |
187 | Set initial the state on `constructor()`. Add DOM event handlers, timers etc on `componentDidMount()`, then remove them on `componentWillUnmount()`.
188 |
189 | ```javascript
190 | constructor (props) # Before rendering
191 | componentWillMount() # Avoid using it
192 | render() # Render
193 | componentDidMount() # After rendering (DOM available)
194 | componentWillUnmount() # Before DOM removal
195 | componentDidCatch() # Catch errors (16+)
196 | ```
197 |
198 | ## Updating
199 |
200 | Called when parents change properties and `setState()`. These are not called for initial renders.
201 |
202 | ```javascript
203 | componentDidUpdate (prevProps, prevState, snapshot) # Use setState() here, but remember to compare props
204 | shouldComponentUpdate (newProps, newState) # Skips render() if returns false
205 | render() # Render
206 | componentDidUpdate (prevProps, prevState) # Operate on the DOM here
207 | ```
208 |
209 | ## State Hook
210 |
211 | ```javascript
212 | import React, { useState } from 'react';
213 |
214 | function Example() {
215 | // Declare a new state variable, which we'll call "count"
216 | const [count, setCount] = useState(0);
217 |
218 | return (
219 |
220 |
You clicked {count} times
221 |
setCount(count + 1)}>
222 | Click me
223 |
224 |
225 | );
226 | }
227 | ```
228 |
229 | ## Effect Hook
230 |
231 | The `useEffect()` Hook can be used as `componentDidMount()`, `componentDidUpdate()`, and `componentWillUnmount()` combined.
232 |
233 | ```javascript
234 | import React, { useState, useEffect } from 'react';
235 |
236 | function Example() {
237 |
238 | const [count, setCount] = useState(0);
239 |
240 | // Similar to componentDidMount and componentDidUpdate:
241 | useEffect(() => {
242 | // Update the document title using the browser API
243 | document.title = `You clicked ${count} times`;
244 | }, [count]);
245 |
246 | return (
247 |
248 |
You clicked {count} times
249 |
setCount(count + 1)}>
250 | Click me
251 |
252 |
253 | );
254 | }
255 | ```
256 |
257 | ## References
258 |
259 | Allows access to DOM nodes.
260 |
261 | ```javascript
262 | class MyComponent extends Component {
263 |
264 | render () {
265 | return (
266 |
267 | this.input = el} />
268 |
269 | )
270 | }
271 |
272 | componentDidMount () {
273 | this.input.focus()
274 | }
275 | }
276 | ```
277 |
278 | ## DOM Events
279 |
280 | Pass functions to attributes like `onChange()`.
281 |
282 | ```javascript
283 | class MyComponent extends Component {
284 |
285 | render () {
286 | this.onChange(event)} />
289 | }
290 |
291 | onChange (event) {
292 | this.setState({ value: event.target.value })
293 | }
294 | }
295 | ```
296 |
297 | ## Transferring props
298 |
299 | Propagates `src="..."` down to the sub-component.
300 |
301 | ```javascript
302 |
303 |
304 | class VideoPlayer extends Component {
305 | render () {
306 | return
307 | }
308 | }
309 | ```
310 |
311 | ## JSX patterns
312 |
313 | ## Style shorthand
314 |
315 | Inline styles
316 |
317 | ```javascript
318 | const style = { height: 10 }
319 | return
320 | return
321 | ```
322 |
323 | ## Conditionals
324 |
325 | ```javascript
326 |
327 | {showMyComponent
328 | ?
329 | : }
330 |
331 | ```
332 |
333 | ## Lists
334 |
335 | ```javascript
336 | class TodoList extends Component {
337 |
338 | render () {
339 | const { items } = this.props
340 |
341 | return
342 | {items.map(item =>
343 | )}
344 |
345 | }
346 | }
347 | ```
348 |
349 | ## Short-circuit evaluation
350 |
351 | ```javascript
352 |
353 | {showPopup && }
354 | ...
355 |
356 | ```
357 |
358 | ## Fragments and Arrays
359 |
360 | ```javascript
361 | // Arrays
362 |
363 | render () {
364 | // Don't forget the keys!
365 | return [
366 | First item ,
367 | Second item
368 | ]
369 | }
370 |
371 | // Fragments
372 | render () {
373 | // Fragments don't require keys!
374 | return (
375 |
376 | First item
377 | Second item
378 |
379 | )
380 | }
381 | ```
382 |
383 | ## Errors
384 |
385 | Catch errors via `componentDidCatch()`.
386 |
387 | ```javascript
388 | class MyComponent extends Component {
389 | ···
390 | componentDidCatch (error, info) {
391 | this.setState({ error })
392 | }
393 | }
394 | ```
395 |
396 | ## Portals
397 |
398 | This renders `this.props.children` into any location in the DOM.
399 |
400 | ```javascript
401 | render () {
402 | return React.createPortal(
403 | this.props.children,
404 | document.getElementById('menu')
405 | )
406 | }
407 | ```
408 |
409 | ## Hydration
410 |
411 | Use `ReactDOM.hydrate()` instead of using `ReactDOM.render()` if you are rendering over the output of ReactDOMServer.
412 |
413 | ```javascript
414 | const el = document.getElementById('app')
415 | ReactDOM.hydrate( , el)
416 | ```
417 |
418 | ## PropTypes
419 |
420 | Typechecking with PropTypes
421 |
422 | ```javascript
423 | import PropTypes from 'prop-types';
424 | ```
425 |
426 | |Property | Description |
427 | |---------------------|-------------|
428 | |any |Anything |
429 | |string | |
430 | |number | |
431 | |func |Function |
432 | |bool |True or false|
433 | |oneOf(any) |Enum types |
434 | |oneOfType(type array)|Union |
435 | |array | |
436 | |arrayOf(…) | |
437 | |object | |
438 | |objectOf(…) | Object with values of a certain type|
439 | |instanceOf(…) |Instance of a class|
440 | |shape(…) | |
441 | |element |React element|
442 | |node |DOM node |
443 | |(···).isRequired |Required |
444 |
445 |
446 | ## Basic types
447 |
448 | ```javascript
449 | MyComponent.propTypes = {
450 | email: PropTypes.string,
451 | seats: PropTypes.number,
452 | callback: PropTypes.func,
453 | isClosed: PropTypes.bool,
454 | any: PropTypes.any
455 | }
456 | ```
457 |
458 | ## Required Types
459 |
460 | ```javascript
461 | MyCo.propTypes = {
462 | name: PropTypes.string.isRequired
463 | }
464 | ```
465 |
466 | ## Elements
467 |
468 | ```javascript
469 | MyCo.propTypes = {
470 | // React element
471 | element: PropTypes.element,
472 |
473 | // num, string, element, or an array of those
474 | node: PropTypes.node
475 | }
476 | ```
477 |
478 | ## Enumerables (oneOf)
479 |
480 | ```javascript
481 | MyCo.propTypes = {
482 | direction: PropTypes.oneOf([
483 | 'left', 'right'
484 | ])
485 | }
486 | ```
487 |
488 | ## Custom validation
489 |
490 | ```javascript
491 | MyCo.propTypes = {
492 |
493 | customProp: (props, key, componentName) => {
494 | if (!/matchme/.test(props[key])) {
495 | return new Error('Validation failed!')
496 | }
497 | }
498 | }
499 | ```
500 |
501 | ## Arrays and Objects
502 |
503 | Use `.arrayOf()`, `.objectOf()`, `.instanceOf()`, `.shape()`.
504 |
505 | ```javascript
506 | MyCo.propTypes = {
507 | list: PropTypes.array,
508 | ages: PropTypes.arrayOf(PropTypes.number),
509 | user: PropTypes.object,
510 | user: PropTypes.objectOf(PropTypes.number),
511 | message: PropTypes.instanceOf(Message)
512 | }
513 | MyCo.propTypes = {
514 | user: PropTypes.shape({
515 | name: PropTypes.string,
516 | age: PropTypes.number
517 | })
518 | }
519 | ```
--------------------------------------------------------------------------------
/redux-quick-reference.md:
--------------------------------------------------------------------------------
1 | # Redux Quick Reference
2 |
3 | ## Creating a store
4 |
5 | A store is made from a reducer function, which takes the current state, and returns a new state depending on the action it was given.
6 |
7 | ```js
8 | import { createStore } from 'redux'
9 |
10 | // Reducer
11 | function counter (state = { value: 0 }, action) {
12 | switch (action.type) {
13 | case 'INCREMENT':
14 | return { value: state.value + 1 }
15 | case 'DECREMENT':
16 | return { value: state.value - 1 }
17 | default:
18 | return state
19 | }
20 | }
21 |
22 | let store = createStore(counter)
23 |
24 | // Optional - you can pass `initialState` as a second arg
25 | let store = createStore(counter, { value: 0 })
26 | ```
27 |
28 |
31 |
32 | ## Using a store
33 |
34 | Dispatch actions to change the store\'s state.
35 |
36 | ```js
37 | let store = createStore(counter)
38 |
39 | // Dispatches an action; this changes the state
40 | store.dispatch({ type: 'INCREMENT' })
41 | store.dispatch({ type: 'DECREMENT' })
42 |
43 | // Gets the current state
44 | store.getState()
45 |
46 | // Listens for changes
47 | store.subscribe(() => { ... })
48 | ```
49 |
50 |
53 |
54 | ## Provider
55 |
56 | The `` component makes the store available in React components. It is used for `connect()`.
57 |
58 | ```js
59 | import { Provider } from 'react-redux'
60 |
61 | React.render(
62 |
63 |
64 | , mountNode)
65 | ```
66 |
67 |
70 |
71 | ## Mapping state
72 |
73 | ```js
74 | import { connect } from 'react-redux'
75 |
76 | // A functional React component
77 | function App ({ message, onMessageClick }) {
78 | return (
79 | onMessageClick('hello')}>
80 | {message}
81 |
82 | )
83 | }
84 |
85 | // Maps `state` to `props`:
86 | // These will be added as props to the component.
87 | function mapState (state) {
88 | return { message: state.message }
89 | }
90 |
91 | // Maps `dispatch` to `props`:
92 | function mapDispatch (dispatch) {
93 | return {
94 | onMessageClick (message) {
95 | dispatch({ type: 'click', message })
96 | }
97 | }
98 | }
99 |
100 | // Connect them:
101 | export default connect(mapState, mapDispatch)(App)
102 | ```
103 |
104 |
107 |
108 | ## Combining reducers
109 |
110 | Combines multiple reducers into one reducer function.
111 |
112 | ```js
113 | const reducer = combineReducers({
114 | counter, user, store
115 | })
116 | ```
117 |
118 |
121 |
122 | ## Signature
123 |
124 | Middlewares are simply decorators for `dispatch()` to allows to take different kinds of actions, and to perform different tasks when receiving actions.
125 |
126 | ```js
127 | // noop middleware
128 | const logger = store => dispatch => action { dispatch(action) }
129 |
130 | const logger = store => {
131 | // This function runs on createStore().
132 | // It returns a decorator for dispatch().
133 |
134 | return dispatch => {
135 | // Runs on createStore(), too.
136 | // It returns a new dispatch() function
137 |
138 | return action => {
139 | // Runs on every dispatch()
140 | }
141 | }
142 | }
143 | ```
144 |
145 |
148 |
149 | ## Applying middleware
150 |
151 | ```js
152 | const enhancer = applyMiddleware(logger, thunk, ...)
153 |
154 | const store = createStore(reducer, {}, enhancer)
155 | ```
156 |
157 |
160 |
--------------------------------------------------------------------------------