@@ -7,32 +7,36 @@ nav: 24
7
7
` createStore ` lets you create a vanilla store that exposes API utilities.
8
8
9
9
``` js
10
- createStore (stateCreatorFn)
10
+ const someStore = createStore (stateCreatorFn)
11
11
```
12
12
13
- - [ Reference ] ( #reference )
13
+ - [ Types ] ( #types )
14
14
- [ Signature] ( #createstore-signature )
15
+ - [ Reference] ( #reference )
15
16
- [ Usage] ( #usage )
16
17
- [ Updating state based on previous state] ( #updating-state-based-on-previous-state )
17
18
- [ Updating Primitives in State] ( #updating-primitives-in-state )
18
19
- [ Updating Objects in State] ( #updating-objects-in-state )
19
20
- [ Updating Arrays in State] ( #updating-arrays-in-state )
20
- - [ Updating state with no store actions] ( #updating-state-with-no-store-actions )
21
21
- [ Subscribing to state updates] ( #subscribing-to-state-updates )
22
22
- [ Troubleshooting] ( #troubleshooting )
23
23
- [ I’ve updated the state, but the screen doesn’t update] ( #ive-updated-the-state-but-the-screen-doesnt-update )
24
24
25
- ## Reference
25
+ ## Types
26
26
27
- ### ` createStore ` Signature
27
+ ### Signature
28
28
29
29
``` ts
30
30
createStore <T >()(stateCreatorFn : StateCreator < T , [], []> ): StoreApi < T >
31
31
```
32
32
33
+ ## Reference
34
+
35
+ ### ` createStore(stateCreatorFn) `
36
+
33
37
#### Parameters
34
38
35
- - ` stateCreatorFn ` : A function that takes ` set ` function, ` get ` function and ` api ` as arguments.
39
+ - ` stateCreatorFn ` : A function that takes ` set ` function, ` get ` function and ` store ` as arguments.
36
40
Usually, you will return an object with the methods you want to expose.
37
41
38
42
#### Returns
@@ -44,7 +48,7 @@ createStore<T>()(stateCreatorFn: StateCreator<T, [], []>): StoreApi<T>
44
48
45
49
### Updating state based on previous state
46
50
47
- This example shows how you can support ** updater functions** for your ** actions** .
51
+ This example shows how you can support ** updater functions** within ** actions** .
48
52
49
53
``` tsx
50
54
import { createStore } from ' zustand/vanilla'
@@ -63,11 +67,10 @@ type AgeStore = AgeStoreState & AgeStoreActions
63
67
64
68
const ageStore = createStore <AgeStore >()((set ) => ({
65
69
age: 42 ,
66
- setAge : (nextAge ) => {
70
+ setAge : (nextAge ) =>
67
71
set ((state ) => ({
68
72
age: typeof nextAge === ' function' ? nextAge (state .age ) : nextAge ,
69
- }))
70
- },
73
+ })),
71
74
}))
72
75
73
76
function increment() {
@@ -135,10 +138,8 @@ $dotContainer.addEventListener('pointermove', (event) => {
135
138
xStore .setState (event .clientX , true )
136
139
})
137
140
138
- const render: Parameters <typeof xStore .subscribe >[0 ] = (state ) => {
139
- const position = { y: 0 , x: state }
140
-
141
- $dot .style .transform = ` translate(${position .x }px, ${position .y }px) `
141
+ const render: Parameters <typeof xStore .subscribe >[0 ] = (x ) => {
142
+ $dot .style .transform = ` translate(${x }px, 0) `
142
143
}
143
144
144
145
render (xStore .getInitialState (), xStore .getInitialState ())
@@ -174,20 +175,17 @@ discards any existing nested data within the state.
174
175
``` ts
175
176
import { createStore } from ' zustand/vanilla'
176
177
177
- type PositionStoreState = { x: number ; y: number }
178
+ type PositionStoreState = { position : { x: number ; y: number } }
178
179
179
180
type PositionStoreActions = {
180
- setPosition: (nextPosition : Partial < PositionStoreState > ) => void
181
+ setPosition: (nextPosition : PositionStoreState [ ' position ' ] ) => void
181
182
}
182
183
183
184
type PositionStore = PositionStoreState & PositionStoreActions
184
185
185
186
const positionStore = createStore <PositionStore >()((set ) => ({
186
- x: 0 ,
187
- y: 0 ,
188
- setPosition : (nextPosition ) => {
189
- set (nextPosition )
190
- },
187
+ position: { x: 0 , y: 0 },
188
+ setPosition : (position ) => set ({ position }),
191
189
}))
192
190
193
191
const $dotContainer = document .getElementById (' dot-container' ) as HTMLDivElement
@@ -201,9 +199,7 @@ $dotContainer.addEventListener('pointermove', (event) => {
201
199
})
202
200
203
201
const render: Parameters <typeof positionStore .subscribe >[0 ] = (state ) => {
204
- const position = { x: state .x , y: state .y }
205
-
206
- $dot .style .transform = ` translate(${position .x }px, ${position .y }px) `
202
+ $dot .style .transform = ` translate(${state .position .x }px, ${state .position .y }px) `
207
203
}
208
204
209
205
render (positionStore .getInitialState (), positionStore .getInitialState ())
@@ -255,10 +251,8 @@ $dotContainer.addEventListener('pointermove', (event) => {
255
251
positionStore .setState ([event .clientX , event .clientY ], true )
256
252
})
257
253
258
- const render: Parameters <typeof positionStore .subscribe >[0 ] = (state ) => {
259
- const position = { x: state [0 ], y: state [1 ] }
260
-
261
- $dot .style .transform = ` translate(${position .x }px, ${position .y }px) `
254
+ const render: Parameters <typeof positionStore .subscribe >[0 ] = ([x , y ]) => {
255
+ $dot .style .transform = ` translate(${x }px, ${y }px) `
262
256
}
263
257
264
258
render (positionStore .getInitialState (), positionStore .getInitialState ())
@@ -288,20 +282,17 @@ updates. We can use `subscribe` for external state management.
288
282
``` ts
289
283
import { createStore } from ' zustand/vanilla'
290
284
291
- type PositionStoreState = { x: number ; y: number }
285
+ type PositionStoreState = { position : { x: number ; y: number } }
292
286
293
287
type PositionStoreActions = {
294
- setPosition: (nextPosition : Partial < PositionStoreState > ) => void
288
+ setPosition: (nextPosition : PositionStoreState [ ' position ' ] ) => void
295
289
}
296
290
297
291
type PositionStore = PositionStoreState & PositionStoreActions
298
292
299
293
const positionStore = createStore <PositionStore >()((set ) => ({
300
- x: 0 ,
301
- y: 0 ,
302
- setPosition : (nextPosition ) => {
303
- set (nextPosition )
304
- },
294
+ position: { x: 0 , y: 0 },
295
+ setPosition : (position ) => set ({ position }),
305
296
}))
306
297
307
298
const $dot = document .getElementById (' dot' ) as HTMLDivElement
@@ -318,17 +309,15 @@ $dot.addEventListener('mouseenter', (event) => {
318
309
})
319
310
320
311
const render: Parameters <typeof positionStore .subscribe >[0 ] = (state ) => {
321
- const position = { x: state .x , y: state .y }
322
-
323
- $dot .style .transform = ` translate(${position .x }px, ${position .y }px) `
312
+ $dot .style .transform = ` translate(${state .position .x }px, ${state .position .y }px) `
324
313
}
325
314
326
315
render (positionStore .getInitialState (), positionStore .getInitialState ())
327
316
328
317
positionStore .subscribe (render )
329
318
330
319
const logger: Parameters <typeof positionStore .subscribe >[0 ] = (state ) => {
331
- console .log (' new position' , { position: { x: state .x , y: state . x } })
320
+ console .log (' new position' , { position: state .position })
332
321
}
333
322
334
323
positionStore .subscribe (logger )
@@ -363,24 +352,22 @@ These input fields don’t work because the `oninput` handlers mutate the state:
363
352
import { createStore } from ' zustand/vanilla'
364
353
365
354
type PersonStoreState = {
366
- firstName: string
367
- lastName: string
368
- email: string
355
+ person: { firstName: string ; lastName: string ; email: string }
369
356
}
370
357
371
358
type PersonStoreActions = {
372
- setPerson: (nextPerson : Partial < PersonStoreState > ) => void
359
+ setPerson: (nextPerson : PersonStoreState [ ' person ' ] ) => void
373
360
}
374
361
375
362
type PersonStore = PersonStoreState & PersonStoreActions
376
363
377
364
const personStore = createStore <PersonStore >()((set ) => ({
378
- firstName: ' Barbara' ,
379
- lastName: ' Hepworth' ,
380
-
381
- setPerson : (nextPerson ) => {
382
- set (nextPerson )
365
+ person: {
366
+ firstName: ' Barbara' ,
367
+ lastName: ' Hepworth' ,
368
+
383
369
},
370
+ setPerson : (person ) => set ({ person }),
384
371
}))
385
372
386
373
const $firstNameInput = document .getElementById (
@@ -391,33 +378,27 @@ const $emailInput = document.getElementById('email') as HTMLInputElement
391
378
const $result = document .getElementById (' result' ) as HTMLDivElement
392
379
393
380
function handleFirstNameChange(event : Event ) {
394
- personStore .getState ().firstName = (event .target as any ).value
381
+ personStore .getState ().person . firstName = (event .target as any ).value
395
382
}
396
383
397
384
function handleLastNameChange(event : Event ) {
398
- personStore .getState ().lastName = (event .target as any ).value
385
+ personStore .getState ().person . lastName = (event .target as any ).value
399
386
}
400
387
401
388
function handleEmailChange(event : Event ) {
402
- personStore .getState ().email = (event .target as any ).value
389
+ personStore .getState ().person . email = (event .target as any ).value
403
390
}
404
391
405
392
$firstNameInput .addEventListener (' input' , handleFirstNameChange )
406
393
$lastNameInput .addEventListener (' input' , handleLastNameChange )
407
394
$emailInput .addEventListener (' input' , handleEmailChange )
408
395
409
396
const render: Parameters <typeof personStore .subscribe >[0 ] = (state ) => {
410
- const person = {
411
- firstName: state .firstName ,
412
- lastName: state .lastName ,
413
- email: state .email ,
414
- }
397
+ $firstNameInput .value = state .person .firstName
398
+ $lastNameInput .value = state .person .lastName
399
+ $emailInput .value = state .person .email
415
400
416
- $firstNameInput .value = person .firstName
417
- $lastNameInput .value = person .lastName
418
- $emailInput .value = person .email
419
-
420
- $result .innerHTML = ` ${person .firstName } ${person .lastName } (${person .email }) `
401
+ $result .innerHTML = ` ${state .person .firstName } ${state .person .lastName } (${state .person .email }) `
421
402
}
422
403
423
404
render (personStore .getInitialState (), personStore .getInitialState ())
@@ -472,24 +453,22 @@ keeping all data grouped in an object is very convenient—as long as you update
472
453
import { createStore } from ' zustand/vanilla'
473
454
474
455
type PersonStoreState = {
475
- firstName: string
476
- lastName: string
477
- email: string
456
+ person: { firstName: string ; lastName: string ; email: string }
478
457
}
479
458
480
459
type PersonStoreActions = {
481
- setPerson: (nextPerson : Partial < PersonStoreState > ) => void
460
+ setPerson: (nextPerson : PersonStoreState [ ' person ' ] ) => void
482
461
}
483
462
484
463
type PersonStore = PersonStoreState & PersonStoreActions
485
464
486
465
const personStore = createStore <PersonStore >()((set ) => ({
487
- firstName: ' Barbara' ,
488
- lastName: ' Hepworth' ,
489
-
490
- setPerson : (nextPerson ) => {
491
- set (nextPerson )
466
+ person: {
467
+ firstName: ' Barbara' ,
468
+ lastName: ' Hepworth' ,
469
+
492
470
},
471
+ setPerson : (person ) => set ({ person }),
493
472
}))
494
473
495
474
const $firstNameInput = document .getElementById (
@@ -501,18 +480,21 @@ const $result = document.getElementById('result') as HTMLDivElement
501
480
502
481
function handleFirstNameChange(event : Event ) {
503
482
personStore .getState ().setPerson ({
483
+ ... personStore .getState ().person ,
504
484
firstName: (event .target as any ).value ,
505
485
})
506
486
}
507
487
508
488
function handleLastNameChange(event : Event ) {
509
489
personStore .getState ().setPerson ({
490
+ ... personStore .getState ().person ,
510
491
lastName: (event .target as any ).value ,
511
492
})
512
493
}
513
494
514
495
function handleEmailChange(event : Event ) {
515
496
personStore .getState ().setPerson ({
497
+ ... personStore .getState ().person ,
516
498
email: (event .target as any ).value ,
517
499
})
518
500
}
@@ -522,17 +504,11 @@ $lastNameInput.addEventListener('input', handleLastNameChange)
522
504
$emailInput .addEventListener (' input' , handleEmailChange )
523
505
524
506
const render: Parameters <typeof personStore .subscribe >[0 ] = (state ) => {
525
- const person = {
526
- firstName: state .firstName ,
527
- lastName: state .lastName ,
528
- email: state .email ,
529
- }
530
-
531
- $firstNameInput .value = person .firstName
532
- $lastNameInput .value = person .lastName
533
- $emailInput .value = person .email
507
+ $firstNameInput .value = state .person .firstName
508
+ $lastNameInput .value = state .person .lastName
509
+ $emailInput .value = state .person .email
534
510
535
- $result .innerHTML = ` ${person .firstName } ${person .lastName } (${person .email }) `
511
+ $result .innerHTML = ` ${state . person .firstName } ${state . person .lastName } (${state . person .email }) `
536
512
}
537
513
538
514
render (personStore .getInitialState (), personStore .getInitialState ())
0 commit comments