mirror of
				https://github.com/reduxjs/redux-devtools.git
				synced 2025-11-04 01:47:25 +03:00 
			
		
		
		
	Proof of concept for state on url
This commit is contained in:
		
							parent
							
								
									28c2062390
								
							
						
					
					
						commit
						06f713baab
					
				| 
						 | 
					@ -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,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';
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										16
									
								
								src/react/LinkToState.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/react/LinkToState.js
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,16 @@
 | 
				
			||||||
 | 
					import React, { PropTypes, Component } from 'react';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default class LogMonitor extends Component {
 | 
				
			||||||
 | 
					  static propTypes = {
 | 
				
			||||||
 | 
					    computedState: PropTypes.object.isRequired
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  render() {
 | 
				
			||||||
 | 
					    const stateUriComponent = encodeURIComponent(JSON.stringify(this.props.computedState));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // TODO: don't blow away other params
 | 
				
			||||||
 | 
					    const urlForThisState = `?reduxDevState=${stateUriComponent}`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return <a href={urlForThisState}>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'
 | 
				
			||||||
| 
						 | 
					@ -177,6 +178,8 @@ export default class LogMonitor extends Component {
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const currentState = computedStates[computedStates.length - 1];
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
      <div style={{...styles.container, backgroundColor: theme.base00}}>
 | 
					      <div style={{...styles.container, backgroundColor: theme.base00}}>
 | 
				
			||||||
        <div style={{...styles.buttonBar, borderColor: theme.base02}}>
 | 
					        <div style={{...styles.buttonBar, borderColor: theme.base02}}>
 | 
				
			||||||
| 
						 | 
					@ -185,6 +188,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 computedState={{ monitorState, skippedActions, stagedActions, computedStates, select }} />
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
        <div style={styles.elements} ref="elements">
 | 
					        <div style={styles.elements} ref="elements">
 | 
				
			||||||
          {elements}
 | 
					          {elements}
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										29
									
								
								src/urlState.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/urlState.js
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,29 @@
 | 
				
			||||||
 | 
					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 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