action
store
dispatcher
view
Object describing what happened
Component routing data to stores (usually by registered callbacks)
Holds some part of state and maintains related logic
Context provides a way to pass data through the component tree without having to pass props down manually at every level
const ThemeContext = React.createContext('light');
First create context and provide default value. We suggest to export context and import it in components later.
class App extends React.Component {
render() {
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
}
The provider will pass a value to all components in the tree below. No matter how deep.
Or pass state from any component to the top.
class MyComponent extends React.Component {
render() {
return (
<ThemeContext.Consumer>
{(context) => {
<Toolbar theme={context} />
}}
</ThemeContext.Consumer>
);
}
}
Component consuming context is wrapped by it.
@Action
@Observer
ViewComponent
Store
@Reaction
calls
notifies
class TickerStore {
@observable tick = 0;
}
@observable is High order function. Wrap another function with it (function currying) or use decorator like above.
class OrderLine {
@observable price = 0;
@observable amount = 1;
constructor(price) { this.price = price; }
@computed get total() { return this.price * this.amount; }
}
Computed value uses other observables to calculate some valueon top of them.
@observer
class Ticker extends React.Component {
render() {
return (
<span>Ticks passed: { this.props.tickerStore.tick } </span>
)
}
};
Observer enables a component to listen to store changes. The store is passed in props. Usually, it is also injected. If you want to use an injection add inject decorator.
class Ticker {
@observable tick = 0;
@action
inkrement = () => { this.tick++ // 'this' will always be correct };
}
const ticker = new Ticker();
setInterval(ticker.increment, 1000);
If some function in store modifies state, mark it as @action.
const reaction = reaction( () =>
todos.map(todo => todo.title), titles => console.log("reaction:", titles.join(", "))
);
Put this code into your store. When something in the store changes than your reaction is called. Autorun is like reaction, but you don't specify on what props you listen.
import DevTools from 'mobx-react-devtools‘;
const App = () => ( <div> ... <DevTools /> </div> );
This will show data, changes, render times…
npm install mobx-react-devtools
Redux is a predictable state container for JavaScript apps. As the requirements for JavaScript single-page applications have become increasingly complicated, our code must manage more state than ever before.
This state can include server responses and cached data, as well as locally created data that has not yet been persisted to the server.
UI state is also increasing in complexity, as we need to manage active routes, selected tabs, spinners, pagination controls, and so on.
The only way to change the state is to emit an action, an object describing what happened.
store.dispatch({
type: 'COMPLETE_TODO‘,
index: 1
})
To specify how the state tree is transformed by actions, you write pure reducers.
function todos(state = [], action) {
switch (action.type) {
case 'COMPLETE_TODO‘:
return state.map((todo, index) => { ... })
default:
return state
}
import { combineReducers, createStore } from 'redux'
const reducer = combineReducers({ todos, someOtherFunction })
const store = createStore(reducer)
import { combineReducers, createStore } from 'redux'
const reducer = combineReducers({ todos, someOtherFunction })
const store = createStore(reducer)
Actions are payloads of information that send data from your application to your store. They are the only source of information for the store. You send them to the store using store.dispatch().
Action creators are exactly that—functions that create actions. It's easy to conflate the terms “action” and “action creator”, so do your best to use the proper term.
function addTodo(text) {
return {
type: ADD_TODO,
text // assigns content of parameter text to field text
}
}
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.
The Store is the object that brings everything together. The store has the following responsibilities:
Holds application state;
Allows access to state via getState();
Allows the state to be updated via dispatch(action);
Registers listeners via subscribe(listener);
Handles unregistering of listeners via the function returned by subscribe(listener)
You have to mam everything to props by creating state mapping function
const mapStateToProps = state => {
return {
todos: getVisibleTodos(state.todos, state.visibilityFilter)
}
}
You also pass in props what actions should happen.
const mapDispatchToProps = dispatch => {
return {
onTodoClick: id => {
dispatch(toggleTodo(id))
}
}
}
And finaly by using HOC store is connected with component
import { connect } from 'react-redux'
const VisibleTodoList = connect(
mapStateToProps,
mapDispatchToProps
)(TodoList)
export default VisibleTodoList