Zustand, der über viele Komponenten verteilt ist, macht Programme kompliziert
Gemeinsame Nutzung von State in unterschiedlichen Komponenten-Hierarchien ist schwierig
Zustandmanagement und UI-Handler werden aus React-Komponenten extrahiert
Besseres SoC
Die klassische Idee
https://mobx.js.org/intro/concepts.html
class Store {
@observable greetings = [];
@observable filter = null;
@computed get filteredGreetings() {
return filterGreetings(this.greetings, this.filter);
}
@action.bound
setFilter(filter) {
if (this.filter === filter) {
// reset filter when clicking again
this.filter = null;
} else {
this.filter = filter;
}
}
}
export default new Store();
import store from './store';
ReactDOM.render(<GreetingController store={store}/>, mountNode);
import {observer} from 'mobx-react';
@observer
export default class GreetingController extends React.Component {
render() {
const {store} = this.props;
const {filteredGreetings} = store;
const {setFilter} = store;
// ...
}
// ...
}
code/experiment/mobx
vertraut
Allerdings: Lernkurve steil, gerade am Anfang wirklich viel Code
Redux ist für kleinere Anwendungen meistens Overkill
MobX erlaubt einen sehr einfachen Einstieg
export function setFilter(filter) {
return {
type: SET_FILTER,
filter
};
}
export const loadGreetings = dispatch => {
return fetch(BACKEND_URL)
.then(response => response.json())
.then(greetings => dispatch({
type: SET_GREETINGS,
greetings
});
);
};
Action-Creators sind die einzigen Teile einer Redux-Anwendung, die asynchrone Operationen ausführen dürfen, wie z.B. eben Server-Calls
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import { rootReducer } from './reducers';
// http://redux.js.org/docs/api/createStore.html
const store = createStore(
rootReducer // reducer
);
ReactDOM.render(
<Provider store={store}>
<GreetingController />
</Provider>,
mountNode
);
import { applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
const store = createStore(
rootReducer, // reducer
applyMiddleware(thunk) // middleware as enhancer
);
import {combineReducers} from 'redux';
// http://redux.js.org/docs/api/combineReducers.html
export const rootReducer = combineReducers({
greetings, // updates greeting partial state
filter,
mode
});
const mode = (state = MODE_MASTER, action) => {
switch (action.type) {
case SET_MODE:
return action.mode;
default:
return state;
}
};
import { connect } from 'react-redux';
import * as actions from './actions';
export default connect(
state => ({
mode: state.mode
// ...
}),
actions
)(GreetingController);
class GreetingController extends React.Component {
render() {
// state from store
const {aggregatedGreetings, greetings, mode} = this.props;
// action creators bound to dispatch from store
const {setMode, saveGreeting, setFilter} = this.props;
// ...
}
}
export const filterGreetings = (greetings, filter) =>
filter ? greetings.filter(greeting => greeting.name === filter)
: greetings;
export default connect(
state => ({
greetings: filterGreetings(state.greetings, state.filter),
// ...
}),
// ...
)(GreetingController);
code/material/6-redux
in deinem Source-Ordner kopieren
combineReducers
hinzu
GreetingController
in die Chart-Komponente in der du auf das
Filter-Event reagierst