Security News
GitHub Removes Malicious Pull Requests Targeting Open Source Repositories
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
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';
import * from './stores/index';
// Let it know about all the stores
@root(stores)
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
We found that redux demonstrated a healthy version release cadence and project activity because the last version was released less than 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
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
Security News
Node.js will be enforcing stricter semver-major PR policies a month before major releases to enhance stability and ensure reliable release candidates.