Skip to content

Commit 9d13413

Browse files
committed
redux toolkit + toolkit and console.log , missing chapters
1 parent 4fa767b commit 9d13413

File tree

1 file changed

+247
-0
lines changed

1 file changed

+247
-0
lines changed

src/content/6/es/part6b.md

Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,253 @@ export default Filter
440440
441441
<div class="content">
442442
443+
### Redux Toolkit
444+
445+
Como hemos visto hasta ahora, la implementación de la gestión del estado y la configuración de Redux requiere bastante esfuerzo. Esto se manifiesta, por ejemplo, en el código relacionado con el reducer y el creador de acciones, que tiene un código repetitivo un tanto repetitivo. [Redux Toolkit](https://redux-toolkit.js.org/) es una librería que resuelve estos problemas comunes relacionados con Redux. La librería, por ejemplo, simplifica enormemente la configuración de la store de Redux y ofrece una gran variedad de herramientas para facilitar la gestión del estado.
446+
447+
Comencemos a usar Redux Toolkit en nuestra aplicación refactorizando el código existente. Primero, necesitaremos instalar la biblioteca:
448+
449+
```
450+
npm install @reduxjs/toolkit
451+
```
452+
453+
A continuación, abra el archivo <i>index.js</i> que actualmente crea la store de Redux. En lugar de la función <em>createStore</em> de Redux, creemos la tienda usando la función [configureStore](https://redux-toolkit.js.org/api/configureStore) de Redux Toolkit:
454+
455+
```js
456+
import React from 'react'
457+
import ReactDOM from 'react-dom/client'
458+
import { Provider } from 'react-redux'
459+
import { configureStore } from '@reduxjs/toolkit' // highlight-line
460+
import App from './App'
461+
462+
import noteReducer from './reducers/noteReducer'
463+
import filterReducer from './reducers/filterReducer'
464+
465+
// highlight-start
466+
const store = configureStore({
467+
reducer: {
468+
notes: noteReducer,
469+
filter: filterReducer
470+
}
471+
})
472+
// highlight-end
473+
474+
console.log(store.getState())
475+
476+
ReactDOM.createRoot(document.getElementById('root')).render(
477+
<Provider store={store}>
478+
<App />
479+
</Provider>
480+
)
481+
```
482+
483+
Ya nos deshicimos de algunas líneas de código ahora que ya no necesitamos la función <em>combineReducers</em> para crear el reducer para la store de Redux. Pronto veremos que la función <em>configureStore</em> tiene muchos beneficios adicionales, como la integración sin esfuerzo de herramientas de desarrollo y muchas librerías de uso común sin necesidad de configuración adicional.
484+
485+
Pasemos a refactorizar los reducers, que representa uno de los beneficios de Redux Toolkit. Con Redux Toolkit, podemos crear fácilmente reducers y creadores de acciones relacionados usando la función [createSlice](https://redux-toolkit.js.org/api/createSlice). Podemos usar la función <em>createSlice</em> para refactorizar el reducer y los creadores de acciones en el archivo <i>reducers/noteReducer.js</i> de la siguiente manera:
486+
487+
```js
488+
import { createSlice } from '@reduxjs/toolkit' // highlight-line
489+
490+
const initialState = [
491+
{
492+
content: 'reducer defines how redux store works',
493+
important: true,
494+
id: 1,
495+
},
496+
{
497+
content: 'state of store can contain any data',
498+
important: false,
499+
id: 2,
500+
},
501+
]
502+
503+
const generateId = () =>
504+
Number((Math.random() * 1000000).toFixed(0))
505+
506+
// highlight-start
507+
const noteSlice = createSlice({
508+
name: 'notes',
509+
initialState,
510+
reducers: {
511+
createNote(state, action) {
512+
const content = action.payload
513+
514+
state.push({
515+
content,
516+
important: false,
517+
id: generateId(),
518+
})
519+
},
520+
toggleImportanceOf(state, action) {
521+
const id = action.payload
522+
523+
const noteToChange = state.find(n => n.id === id)
524+
525+
const changedNote = {
526+
...noteToChange,
527+
important: !noteToChange.important
528+
}
529+
530+
return state.map(note =>
531+
note.id !== id ? note : changedNote
532+
)
533+
}
534+
},
535+
})
536+
// highlight-end
537+
```
538+
539+
El parámetro <em>name</em> de la función <em>createSlice</em> define el prefijo que se utiliza en los valores de tipo de la acción. Por ejemplo, la acción <em>createNote</em> definida más adelante tendrá el valor de tipo <em>notes/createNote</em>. Es una buena práctica dar al parámetro un valor que sea único entre los reducers. De esta forma no habrá colisiones inesperadas entre los valores de tipo de acción de la aplicación. El parámetro <em>initialState</em> define el estado inicial del reducer. El parámetro <em>reducers</em> toma el propio reducer como un objeto, cuyas funciones manejan los cambios de estado causados por ciertas acciones. Tenga en cuenta que <em>action.payload</em> en la función contiene el argumento proporcionado al llamar al creador de la acción:
540+
541+
```js
542+
dispatch(createNote('Redux Toolkit is awesome!'))
543+
```
544+
545+
Esta llamada de <em>dispatch</em> responde al despacho del siguiente objeto:
546+
547+
```js
548+
dispatch({ type: 'notes/createNote', payload: 'Redux Toolkit is awesome!' })
549+
```
550+
551+
Si has seguido todo de cerca, es posible que hayas notado que dentro de la acción <em>createNote</em>, parece suceder algo que viola el principio de inmutabilidad de los reducers mencionado anteriormente:
552+
553+
```js
554+
createNote(state, action) {
555+
const content = action.payload
556+
557+
state.push({
558+
content,
559+
important: false,
560+
id: generateId(),
561+
})
562+
}
563+
```
564+
565+
Estamos mutando el arreglo del parámetro <em>state</em> llamando al método <em>push</em> en lugar de devolver una nueva instancia del arreglo. ¿De qué se trata todo esto?
566+
567+
Redux Toolkit utiliza la librería [Immer](https://immerjs.github.io/immer/) con reducers creados por la función <em>createSlice</em>, que hace posible mutar el parámetro del <em>estado</em> dentro del reducer. Immer usa el estado mutado para producir un nuevo estado inmutable y, por lo tanto, los cambios de estado permanecen inmutables. Tenga en cuenta que el <em>estado</em> se puede cambiar sin "mutarlo", como hemos hecho con la acción <em>toggleImportanceOf</em>. En este caso, la función <i>retorna</i> el nuevo estado. Sin embargo, mutar el estado a menudo será útil, especialmente cuando se necesita actualizar un estado complejo.
568+
569+
La función <em>createSlice</em> retorna un objeto que contiene el reducer así como los creadores de acciones definidos por el parámetro <em>reducers</em>. Se puede acceder al reducer mediante la propiedad <em>noteSlice.reducer</em>, mientras que a los creadores de acciones mediante la propiedad <em>noteSlice.actions</em>. Podemos producir las exportaciones del archivo de la siguiente manera:
570+
571+
```js
572+
const noteSlice = createSlice(/* ... */)
573+
574+
// highlight-start
575+
export const { createNote, toggleImportanceOf } = noteSlice.actions
576+
577+
export default noteSlice.reducer
578+
// highlight-end
579+
```
580+
581+
Las importaciones en otros archivos funcionarán igual que antes:
582+
583+
```js
584+
import noteReducer, { createNote, toggleImportanceOf } from './reducers/noteReducer'
585+
```
586+
587+
Necesitamos modificar los nombres de los tipos de acción en las pruebas debido a las convenciones de ReduxToolkit:
588+
589+
```js
590+
import noteReducer from './noteReducer'
591+
import deepFreeze from 'deep-freeze'
592+
593+
describe('noteReducer', () => {
594+
test('returns new state with action notes/createNote', () => {
595+
const state = []
596+
const action = {
597+
type: 'notes/createNote', // highlight-line
598+
payload: 'the app state is in redux store', // highlight-line
599+
}
600+
601+
deepFreeze(state)
602+
const newState = noteReducer(state, action)
603+
604+
expect(newState).toHaveLength(1)
605+
expect(newState.map(s => s.content)).toContainEqual(action.payload)
606+
})
607+
608+
test('returns new state with action notes/toggleImportanceOf', () => {
609+
const state = [
610+
{
611+
content: 'the app state is in redux store',
612+
important: true,
613+
id: 1
614+
},
615+
{
616+
content: 'state changes are made with actions',
617+
important: false,
618+
id: 2
619+
}]
620+
621+
const action = {
622+
type: 'notes/toggleImportanceOf', // highlight-line
623+
payload: 2
624+
}
625+
626+
deepFreeze(state)
627+
const newState = noteReducer(state, action)
628+
629+
expect(newState).toHaveLength(2)
630+
631+
expect(newState).toContainEqual(state[0])
632+
633+
expect(newState).toContainEqual({
634+
content: 'state changes are made with actions',
635+
important: true,
636+
id: 2
637+
})
638+
})
639+
})
640+
```
641+
642+
### Redux Toolkit and console.log
643+
644+
Como hemos aprendido, console.log es una herramienta extremadamente poderosa, por lo general siempre nos salva de problemas.
645+
646+
Intentemos imprimir el estado de la store de Redux en la consola en medio del reductor creado con la función createSlice:
647+
648+
```js
649+
const noteSlice = createSlice({
650+
name: 'notes',
651+
initialState,
652+
reducers: {
653+
// ...
654+
toggleImportanceOf(state, action) {
655+
const id = action.payload
656+
657+
const noteToChange = state.find(n => n.id === id)
658+
659+
const changedNote = {
660+
...noteToChange,
661+
important: !noteToChange.important
662+
}
663+
664+
console.log(state) // highlight-line
665+
666+
return state.map(note =>
667+
note.id !== id ? note : changedNote
668+
)
669+
}
670+
},
671+
})
672+
```
673+
674+
Lo siguiente se imprime en la consola
675+
676+
![](../../images/6/40new.png)
677+
678+
La salida es interesante pero no muy útil. Esto trata de la librería Immer mencionada anteriormente utilizada por Redux Toolkit, que ahora se usa internamente para guardar el estado de la Tienda.
679+
680+
El estado se puede convertir a un formato legible por humanos, e.j. convirtiéndolo en una cadena y de nuevo en un objeto JavaScript de la siguiente manera:
681+
682+
```js
683+
console.log(JSON.parse(JSON.stringify(state))) // highlight-line
684+
```
685+
686+
La salida de la consola ahora es legible para humanos
687+
688+
![](../../images/6/41new.png)
689+
443690
### Redux DevTools
444691
445692
[Redux DevTools](https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd) es una extension de Chrome, que ofrece útiles herramientas de desarrollo para Redux. Se puede usar, por ejemplo, para inspeccionar el estado del store de Redux y enviar acciones (dispatch) a través de la consola del navegador. Cuando el store se crea usando la función <em>configureStore</em> de Redux Toolkit, no se necesita ninguna configuración adicional para que Redux DevTools funcione.

0 commit comments

Comments
 (0)