
Security News
Crates.io Implements Trusted Publishing Support
Crates.io adds Trusted Publishing support, enabling secure GitHub Actions-based crate releases without long-lived API tokens.
Redux is a predictable state container for JavaScript apps. It helps you write applications that behave consistently, run in different environments (client, server, and native), and are easy to test. Redux provides a single source of truth for your application's state, making state mutations predictable through a strict unidirectional data flow.
State Management
Redux provides a store that holds the state tree of your application. You can dispatch actions to change the state, and subscribe to updates.
const { createStore } = require('redux');
function counter(state = 0, action) {
switch (action.type) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
}
let store = createStore(counter);
store.subscribe(() => console.log(store.getState()));
store.dispatch({ type: 'INCREMENT' });
// The current state is 1
store.dispatch({ type: 'INCREMENT' });
// The current state is 2
store.dispatch({ type: 'DECREMENT' });
// The current state is 1
Actions
Actions are payloads of information that send data from your application to your store. They are the only source of information for the store.
function addTodo(text) {
return {
type: 'ADD_TODO',
text
};
}
store.dispatch(addTodo('Learn Redux'));
Reducers
Reducers specify how the application's state changes in response to actions sent to the store. Remember that actions only describe what happened, but don't describe how the application's state changes.
function todos(state = [], action) {
switch (action.type) {
case 'ADD_TODO':
return state.concat([action.text]);
default:
return state;
}
}
Middleware
Middleware extends Redux with custom functionality. It lets you wrap the store's dispatch method for fun and profit. A very common use is for dealing with asynchronous actions.
const { applyMiddleware, createStore } = require('redux');
const createLogger = require('redux-logger');
const logger = createLogger();
const store = createStore(
reducer,
applyMiddleware(logger)
);
MobX is a battle-tested library that makes state management simple and scalable by transparently applying functional reactive programming (TFRP). Unlike Redux, which uses a single store and requires you to dispatch actions to change your state, MobX allows you to create multiple stores and uses observables to automatically track changes in state through actions.
Vuex is a state management pattern + library for Vue.js applications. It serves as a centralized store for all the components in an application, with rules ensuring that the state can only be mutated in a predictable fashion. It is very similar to Redux but is tailored specifically for the Vue.js framework.
Flux is the application architecture that Facebook uses for building client-side web applications. It complements React's composable view components by utilizing a unidirectional data flow. It's more of a pattern rather than a formal framework, and you can start using Flux immediately without a lot of new code. Redux was actually inspired by Flux and can be considered its evolution.
Immer is a tiny package that allows you to work with immutable state in a more convenient way. It is based on the copy-on-write mechanism. The main difference from Redux is that Immer allows you to write code that looks like it's mutating state directly, without actually mutating the state.
An experiment in fully hot-reloadable Flux.
The API might change any day.
Don't use in production.
Read The Evolution of Flux Frameworks for some context.
createAction
, createStores
, wrapThisStuff
. Your stuff is your stuff.git clone https://github.com/gaearon/redux.git redux
cd redux
npm install
npm start
// Still using constants...
import {
INCREMENT_COUNTER,
DECREMENT_COUNTER
} from '../constants/ActionTypes';
// But action creators are pure functions returning actions
export function increment() {
return {
type: INCREMENT_COUNTER
};
}
export function decrement() {
return {
type: DECREMENT_COUNTER
};
}
// Can also be async if you return a function
// (wow, much functions, so injectable :doge:)
export function incrementAsync() {
return dispatch => {
setTimeout(() => {
dispatch(increment());
}, 1000);
};
}
// Could also look into state in the callback form
export function incrementIfOdd() {
return (dispatch, state) => {
if (state.counterStore.counter % 2 === 0) {
return;
}
dispatch(increment());
};
}
// ... too, use constants
import {
INCREMENT_COUNTER,
DECREMENT_COUNTER
} from '../constants/ActionTypes';
// but you can write this part anyhow you like:
const initialState = { counter: 0 };
function increment({ counter }) {
return { counter: counter + 1 };
}
function decrement({ counter }) {
return { counter: counter - 1 };
}
// what's important is that Store is a pure function too
export default function counterStore(state = initialState, action) {
// that returns the new state when an action comes
switch (action.type) {
case INCREMENT_COUNTER:
return increment(state, action);
case DECREMENT_COUNTER:
return decrement(state, action);
default:
return state;
}
}
// bonus: no special support needed for ImmutableJS,
// just return its objects as the state.
// The dumb component receives everything using props:
import React, { PropTypes } from 'react';
export default class Counter {
static propTypes = {
counter: PropTypes.number.isRequired,
increment: PropTypes.func.isRequired,
decrement: PropTypes.func.isRequired
};
render() {
const { counter } = this.props;
return (
<p>
Clicked: {counter} times
</p>
);
}
}
// The smart component may inject actions
// and observe stores using <Container />:
import React, { Component } from 'react';
import { Root, Container } from 'redux';
import { increment, decrement } from './actions/CounterActions';
import counterStore from './stores/counterStore';
import Counter from './Counter';
export default class CounterContainer {
render() {
// stores must be an array.
// actions must be a string -> function map.
// props passed to children will combine these actions and state.
return (
<Container stores={[counterStore]}
actions={{ increment, decrement }}>
{props => <Counter {...props} />}
</Container>
);
}
}
Don't want to separate dumb and smart components just yet? Use the decorators!
They work exactly the same as the container components, but are lowercase:
import React, { PropTypes } from 'react';
import { increment, decrement } from './actions/CounterActions';
import { container } from 'redux';
import counterStore from './stores/counterStore';
@container({
actions: { increment, decrement },
stores: [counterStore]
})
export default class Counter {
static propTypes = {
increment: PropTypes.func.isRequired,
decrement: PropTypes.func.isRequired,
counter: PropTypes.number.isRequired
};
render() {
return (
<p>
Clicked: {this.props.counter} times
{' '}
<button onClick={() => this.props.increment()}>+</button>
{' '}
<button onClick={() => this.props.decrement()}>-</button>
</p>
);
}
}
import React from 'react';
import { Root } from 'redux';
@Root
export default class App {
/* ... */
}
module.hot
lines in the dispatcher example aboveI wouldn't. Many use cases are not be considered yet. If you find some use cases this lib can't handle yet, please file an issue.
FAQs
Predictable state container for JavaScript apps
The npm package redux receives a total of 9,108,201 weekly downloads. As such, redux popularity was classified as popular.
We found that redux demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 6 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Crates.io adds Trusted Publishing support, enabling secure GitHub Actions-based crate releases without long-lived API tokens.
Research
/Security News
Undocumented protestware found in 28 npm packages disrupts UI for Russian-language users visiting Russian and Belarusian domains.
Research
/Security News
North Korean threat actors deploy 67 malicious npm packages using the newly discovered XORIndex malware loader.