mirror of
https://github.com/reduxjs/redux-devtools.git
synced 2025-07-27 08:30:02 +03:00
Merge ce49aafc4d
into f028569a60
This commit is contained in:
commit
68b22f3c4b
|
@ -1,16 +1,20 @@
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import CounterApp from './CounterApp';
|
import CounterApp from './CounterApp';
|
||||||
import { createStore, applyMiddleware, combineReducers, compose } from 'redux';
|
import { createStore, applyMiddleware, combineReducers, compose } from 'redux';
|
||||||
import { devTools, persistState } from 'redux-devtools';
|
import { devTools, persistState, urlState } from 'redux-devtools';
|
||||||
import { DevTools, DebugPanel, LogMonitor } from 'redux-devtools/lib/react';
|
import { DevTools, DebugPanel, LogMonitor } from 'redux-devtools/lib/react';
|
||||||
import thunk from 'redux-thunk';
|
import thunk from 'redux-thunk';
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
import * as reducers from '../reducers';
|
import * as reducers from '../reducers';
|
||||||
|
|
||||||
|
const devStateJsonMatches = window.location.href.match(/[?&]dev_state=([^&]+)\b/);
|
||||||
|
const devStateJson = devStateJsonMatches ? devStateJsonMatches[1] : null;
|
||||||
|
|
||||||
const finalCreateStore = compose(
|
const finalCreateStore = compose(
|
||||||
applyMiddleware(thunk),
|
applyMiddleware(thunk),
|
||||||
devTools(),
|
devTools(),
|
||||||
persistState(window.location.href.match(/[?&]debug_session=([^&]+)\b/))
|
persistState(window.location.href.match(/[?&]debug_session=([^&]+)\b/)),
|
||||||
|
urlState(devStateJson),
|
||||||
)(createStore);
|
)(createStore);
|
||||||
|
|
||||||
const reducer = combineReducers(reducers);
|
const reducer = combineReducers(reducers);
|
||||||
|
|
|
@ -1,14 +1,19 @@
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import TodoApp from './TodoApp';
|
import TodoApp from './TodoApp';
|
||||||
import { createStore, combineReducers, compose } from 'redux';
|
import { createStore, combineReducers, compose } from 'redux';
|
||||||
import { devTools, persistState } from 'redux-devtools';
|
import { devTools, persistState, urlState } from 'redux-devtools';
|
||||||
import { DevTools, DebugPanel, LogMonitor } from 'redux-devtools/lib/react';
|
import { DevTools, DebugPanel, LogMonitor } from 'redux-devtools/lib/react';
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
import * as reducers from '../reducers';
|
import * as reducers from '../reducers';
|
||||||
|
|
||||||
|
|
||||||
|
const devStateJsonMatches = window.location.href.match(/[?&]dev_state=([^&]+)\b/);
|
||||||
|
const devStateJson = devStateJsonMatches ? devStateJsonMatches[1] : null;
|
||||||
|
|
||||||
const finalCreateStore = compose(
|
const finalCreateStore = compose(
|
||||||
devTools(),
|
devTools(),
|
||||||
persistState(window.location.href.match(/[?&]debug_session=([^&]+)\b/))
|
persistState(window.location.href.match(/[?&]debug_session=([^&]+)\b/)),
|
||||||
|
urlState(devStateJson)
|
||||||
)(createStore);
|
)(createStore);
|
||||||
|
|
||||||
const reducer = combineReducers(reducers);
|
const reducer = combineReducers(reducers);
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
export { default as devTools } from './devTools';
|
export { default as devTools } from './devTools';
|
||||||
export { default as persistState } from './persistState';
|
export { default as persistState } from './persistState';
|
||||||
|
export { default as urlState } from './urlState';
|
||||||
|
|
21
src/react/LinkToState.js
Normal file
21
src/react/LinkToState.js
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import React, { PropTypes, Component } from 'react';
|
||||||
|
import { getUrlForState } from '../urlState';
|
||||||
|
|
||||||
|
const styles = {
|
||||||
|
link: {
|
||||||
|
color: '#6FB3D2'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class LinkToState extends Component {
|
||||||
|
static propTypes = {
|
||||||
|
fullAppState: PropTypes.object.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const urlForState = getUrlForState(this.props.fullAppState);
|
||||||
|
return <a style={{...styles.link}} href={urlForState}>
|
||||||
|
Current State
|
||||||
|
</a>;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
import React, { PropTypes, findDOMNode, Component } from 'react';
|
import React, { PropTypes, findDOMNode, Component } from 'react';
|
||||||
import LogMonitorEntry from './LogMonitorEntry';
|
import LogMonitorEntry from './LogMonitorEntry';
|
||||||
import LogMonitorButton from './LogMonitorButton';
|
import LogMonitorButton from './LogMonitorButton';
|
||||||
|
import LinkToState from './LinkToState';
|
||||||
import * as themes from './themes';
|
import * as themes from './themes';
|
||||||
|
|
||||||
const styles = {
|
const styles = {
|
||||||
|
@ -25,7 +26,7 @@ const styles = {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
left: 0,
|
left: 0,
|
||||||
right: 0,
|
right: 0,
|
||||||
top: 38,
|
top: 76,
|
||||||
bottom: 0,
|
bottom: 0,
|
||||||
overflowX: 'hidden',
|
overflowX: 'hidden',
|
||||||
overflowY: 'auto'
|
overflowY: 'auto'
|
||||||
|
@ -185,6 +186,9 @@ export default class LogMonitor extends Component {
|
||||||
<LogMonitorButton theme={theme} onClick={::this.handleSweep} enabled={Object.keys(skippedActions).some(key => skippedActions[key])}>Sweep</LogMonitorButton>
|
<LogMonitorButton theme={theme} onClick={::this.handleSweep} enabled={Object.keys(skippedActions).some(key => skippedActions[key])}>Sweep</LogMonitorButton>
|
||||||
<LogMonitorButton theme={theme} onClick={::this.handleCommit} enabled={computedStates.length > 1}>Commit</LogMonitorButton>
|
<LogMonitorButton theme={theme} onClick={::this.handleCommit} enabled={computedStates.length > 1}>Commit</LogMonitorButton>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<LinkToState fullAppState={ this.props.store.getState() } />
|
||||||
|
</div>
|
||||||
<div style={styles.elements} ref="elements">
|
<div style={styles.elements} ref="elements">
|
||||||
{elements}
|
{elements}
|
||||||
</div>
|
</div>
|
||||||
|
|
35
src/urlState.js
Normal file
35
src/urlState.js
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
function serializeState(state) {
|
||||||
|
return encodeURIComponent(JSON.stringify(state));
|
||||||
|
}
|
||||||
|
|
||||||
|
function deserializeState(json) {
|
||||||
|
try {
|
||||||
|
return JSON.parse(decodeURIComponent(json));
|
||||||
|
} catch (e) {
|
||||||
|
console.log(json);
|
||||||
|
console.error('Could not parse state from Url', e);
|
||||||
|
console.log('To continue, remove query param that\'s trying to set state!');
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getUrlForState(state) {
|
||||||
|
const stateUriComponent = serializeState(state);
|
||||||
|
|
||||||
|
// TODO: don't blow away other params
|
||||||
|
return `?dev_state=${stateUriComponent}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function urlEncodedStateReducer(stateUriComponent) {
|
||||||
|
return next => (reducer, initialState) => {
|
||||||
|
let store;
|
||||||
|
if (stateUriComponent) {
|
||||||
|
const stateOnUrl = deserializeState(stateUriComponent);
|
||||||
|
store = next(reducer, stateOnUrl);
|
||||||
|
} else {
|
||||||
|
store = next(reducer, initialState);
|
||||||
|
}
|
||||||
|
|
||||||
|
return store;
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user