Файл custom-provider.js, позволяющий помимо доступа к store вызывать функцию setAppState(), обновляющую state всего приложения и перерисовывающая его.
import React, {Component, PropTypes, Children} from 'react';
let didWarnAboutReceivingStore = false;
function warnAboutReceivingStore () {
if (didWarnAboutReceivingStore) {return;}
didWarnAboutReceivingStore = true;
warning(
'<Provider> does not support changing `store` on the fly. '
+ 'It is most likely that you see this error because you updated to '
+ 'Redux 2.x and React Redux 2.x which no longer hot reload reducers '
+ 'automatically. See https://github.com/reactjs/react-redux/releases/'
+ 'tag/v2.0.0 for the migration instructions.'
);
}
// Prints a warning in the console if it exists.
// @param {String} message The warning message.
// @returns {void}
function warning (message) {
/* eslint-disable no-console */
if (typeof console !== 'undefined' && typeof console.error === 'function') {
console.error(message);
}
/* eslint-enable no-console */
try {
// This error was thrown as a convenience so that if you enable
// "break on all exceptions" in your console,
// it would pause the execution at this line.
throw new Error(message);
/* eslint-disable no-empty */
} catch (e) {}
/* eslint-enable no-empty */
}
export default class Provider extends Component {
getChildContext () {
return {
store: this.store
, setAppState: this.setState.bind(this)
};
}
constructor (props, context) {
super(props, context)
this.store = props.store;
}
render () {
return Children.only(this.props.children);
}
}
if (process.env.NODE_ENV !== 'production') {
Provider.prototype.componentWillReceiveProps = function (nextProps) {
const store = this.store
, nextStore = nextProps.store;
if (store !== nextStore) {warnAboutReceivingStore();}
}
}
const storeShape = PropTypes.shape({
subscribe: PropTypes.func.isRequired
, dispatch: PropTypes.func.isRequired
, getState: PropTypes.func.isRequired
});
Provider.propTypes = {
store: storeShape.isRequired
, children: PropTypes.element.isRequired
};
Provider.childContextTypes = {
store: storeShape.isRequired
, setAppState: React.PropTypes.func
};
Файл index.js с примером кода приложения.
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import {createStore, combineReducers} from 'redux';
import Provider from './custom-provider.js';
class RandomNumberGenerator extends Component {
constructor (props, context) {
super(props, context);
this.store = this.context.store;
this.setAppState = this.context.setAppState;
}
render () {
return (
<div>
<p>Текущее случайное число = {this.store.getState().randomNumber}</p>
<div style={{display: 'inline-block', border: '1px solid black'}} onClick={this.handleClick.bind(this)}>Сгенерировать новое случайное число</div>
</div>
);
}
handleClick () {
this.store.dispatch({type: 'GENERATE_RANDOM_NUMBER'});
this.setAppState({});
}
shouldComponentUpdate () {
console.log('RandomNumberGenerator updated');
return true;
}
}
RandomNumberGenerator.contextTypes = {
store: React.PropTypes.object
, setAppState: React.PropTypes.func
};
class Hello extends Component {
constructor (props, context) {
super(props, context);
this.store = this.context.store;
}
render () {
return (
<div>
<h1>Привет! Ваше случайное число = {this.store.getState().randomNumber}</h1>
<RandomNumberGenerator />
</div>
);
}
shouldComponentUpdate () {
console.log('Hello updated');
return true;
}
}
Hello.contextTypes = {
store: React.PropTypes.object
};
class App extends Component {
render () {
return <Hello />;
}
}
var initialState = {randomNumber: 0.2841463617514819};
function randomNumberReducer (state = initialState.randomNumber, action) {
switch (action.type) {
case 'GENERATE_RANDOM_NUMBER': return Math.random();
default: return state;
}
}
var rootReducer = combineReducers({
randomNumber: randomNumberReducer
});
const store = createStore(rootReducer, initialState);
ReactDOM.render(<Provider store={store}><App /></Provider>, document.getElementById('app'));
Файл index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>React Redux Webpack</title>
</head>
<body>
<div id="app"></div>
<script type="text/javascript" src="../dist/bundle.js"></script>
</body>
</html>
Комментариев нет:
Отправить комментарий