-
How to reset state in Redux?
You need to write a root reducer in your application which delegate handling the action to the reducer generated by
combineReducers().For example, let us take
rootReducer()to return the initial state afterUSER_LOGOUTaction. As we know, reducers are supposed to return the initial state when they are called withundefinedas the first argument, no matter the action.const appReducer = combineReducers({ /* your app's top-level reducers */ }) const rootReducer = (state, action) => { if (action.type === 'USER_LOGOUT') { state = undefined } return appReducer(state, action) }In case of using
redux-persist, you may also need to clean your storage.redux-persistkeeps a copy of your state in a storage engine. First, you need to import the appropriate storage engine and then, to parse the state before setting it to undefined and clean each storage state key.const appReducer = combineReducers({ /* your app's top-level reducers */ }) const rootReducer = (state, action) => { if (action.type === 'USER_LOGOUT') { Object.keys(state).forEach(key => { storage.removeItem(`persist:${key}`) }) state = undefined } return appReducer(state, action) } -
Whats the purpose of
atsymbol in the Redux connect decorator?The @ symbol is in fact a JavaScript expression used to signify decorators. Decorators make it possible to annotate and modify classes and properties at design time.
Let's take an example setting up Redux without and with a decorator.
-
Without decorator:
import React from 'react' import * as actionCreators from './actionCreators' import { bindActionCreators } from 'redux' import { connect } from 'react-redux' function mapStateToProps(state) { return { todos: state.todos } } function mapDispatchToProps(dispatch) { return { actions: bindActionCreators(actionCreators, dispatch) } } class MyApp extends React.Component { // ...define your main app here } export default connect(mapStateToProps, mapDispatchToProps)(MyApp) -
With decorator:
import React from 'react' import * as actionCreators from './actionCreators' import { bindActionCreators } from 'redux' import { connect } from 'react-redux' function mapStateToProps(state) { return { todos: state.todos } } function mapDispatchToProps(dispatch) { return { actions: bindActionCreators(actionCreators, dispatch) } } @connect(mapStateToProps, mapDispatchToProps) export default class MyApp extends React.Component { // ...define your main app here }
The above examples are almost similar except the usage of decorator. The decorator syntax isn't built into any JavaScript runtimes yet, and is still experimental and subject to change. You can use babel for the decorators support.
-
-
What is the difference between React context and React Redux?
You can use Context in your application directly and is going to be great for passing down data to deeply nested components which what it was designed for.
Whereas Redux is much more powerful and provides a large number of features that the Context API doesn't provide. Also, React Redux uses context internally but it doesn't expose this fact in the public API.
-
Why are Redux state functions called reducers?
Reducers always return the accumulation of the state (based on all previous and current actions). Therefore, they act as a reducer of state. Each time a Redux reducer is called, the state and action are passed as parameters. This state is then reduced (or accumulated) based on the action, and then the next state is returned. You could reduce a collection of actions and an initial state (of the store) on which to perform these actions to get the resulting final state.
-
How to make AJAX request in Redux?
You can use
redux-thunkmiddleware which allows you to define async actions.Let's take an example of fetching specific account as an AJAX call using fetch API:
export function fetchAccount(id) { return dispatch => { dispatch(setLoadingAccountState()) // Show a loading spinner fetch(`/account/${id}`, (response) => { dispatch(doneFetchingAccount()) // Hide loading spinner if (response.status === 200) { dispatch(setAccount(response.json)) // Use a normal function to set the received state } else { dispatch(someError) } }) } } function setAccount(data) { return { type: 'SET_Account', data: data } } -
Should I keep all component's state in Redux store?
Keep your data in the Redux store, and the UI related state internally in the component.
-
What is the proper way to access Redux store?
The best way to access your store in a component is to use the
connect()function, that creates a new component that wraps around your existing one. This pattern is called Higher-Order Components, and is generally the preferred way of extending a component's functionality in React. This allows you to map state and action creators to your component, and have them passed in automatically as your store updates.Let's take an example of
<FilterLink>component using connect:import { connect } from 'react-redux' import { setVisibilityFilter } from '../actions' import Link from '../components/Link' const mapStateToProps = (state, ownProps) => ({ active: ownProps.filter === state.visibilityFilter }) const mapDispatchToProps = (dispatch, ownProps) => ({ onClick: () => dispatch(setVisibilityFilter(ownProps.filter)) }) const FilterLink = connect( mapStateToProps, mapDispatchToProps )(Link) export default FilterLinkDue to it having quite a few performance optimizations and generally being less likely to cause bugs, the Redux developers almost always recommend using
connect()over accessing the store directly (using context API).class MyComponent { someMethod() { doSomethingWith(this.context.store) } } -
What is the difference between component and container in React Redux?
Component is a class or function component that describes the presentational part of your application.
Container is an informal term for a component that is connected to a Redux store. Containers subscribe to Redux state updates and dispatch actions, and they usually don't render DOM elements; they delegate rendering to presentational child components.
-
What is the purpose of the constants in Redux?
Constants allows you to easily find all usages of that specific functionality across the project when you use an IDE. It also prevents you from introducing silly bugs caused by typos – in which case, you will get a
ReferenceErrorimmediately.Normally we will save them in a single file (
constants.jsoractionTypes.js).export const ADD_TODO = 'ADD_TODO' export const DELETE_TODO = 'DELETE_TODO' export const EDIT_TODO = 'EDIT_TODO' export const COMPLETE_TODO = 'COMPLETE_TODO' export const COMPLETE_ALL = 'COMPLETE_ALL' export const CLEAR_COMPLETED = 'CLEAR_COMPLETED'In Redux, you use them in two places:
-
During action creation:
Let's take
actions.js:import { ADD_TODO } from './actionTypes'; export function addTodo(text) { return { type: ADD_TODO, text } } -
In reducers:
Let's create
reducer.js:import { ADD_TODO } from './actionTypes' export default (state = [], action) => { switch (action.type) { case ADD_TODO: return [ ...state, { text: action.text, completed: false } ]; default: return state } }
-
-
What are the different ways to write
mapDispatchToProps()?There are a few ways of binding action creators to
dispatch()inmapDispatchToProps().Below are the possible options:
const mapDispatchToProps = (dispatch) => ({ action: () => dispatch(action()) })const mapDispatchToProps = (dispatch) => ({ action: bindActionCreators(action, dispatch) })const mapDispatchToProps = { action }The third option is just a shorthand for the first one.