mirror of
				https://github.com/reduxjs/redux-devtools.git
				synced 2025-10-31 16:07:45 +03:00 
			
		
		
		
	* Replace Action<unknown> with Action<string> In anticipation of Redux 5 type changes * Fix lint errors * Create yellow-steaks-marry.md
		
			
				
	
	
		
			153 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			153 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import React, { Component } from 'react';
 | |
| 
 | |
| import { getStackFrames } from './react-error-overlay/utils/getStackFrames';
 | |
| import StackTrace from './react-error-overlay/containers/StackTrace';
 | |
| import openFile from './openFile';
 | |
| import { Action } from 'redux';
 | |
| import { TabComponentProps } from '@redux-devtools/inspector-monitor';
 | |
| import StackFrame from './react-error-overlay/utils/stack-frame';
 | |
| import { ErrorLocation } from './react-error-overlay/utils/parseCompileError';
 | |
| 
 | |
| const rootStyle = { padding: '5px 10px' };
 | |
| 
 | |
| interface Props<S, A extends Action<string>> extends TabComponentProps<S, A> {
 | |
|   openFile: (
 | |
|     fileName: string,
 | |
|     lineNumber: number,
 | |
|     stackFrame: StackFrame,
 | |
|   ) => void;
 | |
| }
 | |
| 
 | |
| interface State {
 | |
|   stackFrames: StackFrame[];
 | |
|   currentError?: Error;
 | |
|   showDocsLink?: boolean;
 | |
| }
 | |
| 
 | |
| export class TraceTab<S, A extends Action<string>> extends Component<
 | |
|   Props<S, A>,
 | |
|   State
 | |
| > {
 | |
|   static defaultProps = {
 | |
|     openFile,
 | |
|   };
 | |
| 
 | |
|   state: State = {
 | |
|     stackFrames: [],
 | |
|   };
 | |
| 
 | |
|   componentDidMount() {
 | |
|     // console.log("StackTraceTab mounted");
 | |
|     this.checkForStackTrace();
 | |
|   }
 | |
| 
 | |
|   componentDidUpdate(prevProps: Props<S, A>) {
 | |
|     const { action, actions } = prevProps;
 | |
| 
 | |
|     if (action !== this.props.action || actions !== this.props.actions) {
 | |
|       this.checkForStackTrace();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   checkForStackTrace() {
 | |
|     const { action, actions: liftedActionsById } = this.props;
 | |
| 
 | |
|     if (!action) {
 | |
|       return;
 | |
|     }
 | |
| 
 | |
|     const liftedActions = Object.values(liftedActionsById);
 | |
|     const liftedAction = liftedActions.find(
 | |
|       (liftedAction) => liftedAction.action === action,
 | |
|     );
 | |
| 
 | |
|     if (liftedAction && typeof liftedAction.stack === 'string') {
 | |
|       const deserializedError = Object.assign(new Error(), {
 | |
|         stack: liftedAction.stack,
 | |
|       });
 | |
| 
 | |
|       getStackFrames(deserializedError)
 | |
|         .then((stackFrames) => {
 | |
|           this.setState({
 | |
|             stackFrames: stackFrames!,
 | |
|             currentError: deserializedError,
 | |
|           });
 | |
|         })
 | |
|         .catch(() => {
 | |
|           // noop
 | |
|         });
 | |
|     } else {
 | |
|       this.setState({
 | |
|         stackFrames: [],
 | |
|         showDocsLink:
 | |
|           !!liftedAction!.action &&
 | |
|           !!liftedAction!.action.type &&
 | |
|           liftedAction!.action.type !== '@@INIT',
 | |
|       });
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   onStackLocationClicked = (fileLocation: Partial<ErrorLocation> = {}) => {
 | |
|     // console.log("Stack location args: ", ...args);
 | |
| 
 | |
|     const { fileName, lineNumber } = fileLocation;
 | |
| 
 | |
|     if (fileName && lineNumber) {
 | |
|       const matchingStackFrame = this.state.stackFrames.find((stackFrame) => {
 | |
|         const matches =
 | |
|           (stackFrame._originalFileName === fileName &&
 | |
|             stackFrame._originalLineNumber === lineNumber) ||
 | |
|           (stackFrame.fileName === fileName &&
 | |
|             stackFrame.lineNumber === lineNumber);
 | |
|         return matches;
 | |
|       });
 | |
| 
 | |
|       // console.log("Matching stack frame: ", matchingStackFrame);
 | |
| 
 | |
|       if (matchingStackFrame) {
 | |
|         /*
 | |
|         const frameIndex = this.state.stackFrames.indexOf(matchingStackFrame);
 | |
|         const originalStackFrame = parsedFramesNoSourcemaps[frameIndex];
 | |
|         console.log("Original stack frame: ", originalStackFrame);
 | |
|         */
 | |
|         this.props.openFile(fileName, lineNumber, matchingStackFrame);
 | |
|       }
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   openDocs: React.MouseEventHandler<HTMLAnchorElement> = (e) => {
 | |
|     e.stopPropagation();
 | |
|     window.open(
 | |
|       'https://github.com/zalmoxisus/redux-devtools-extension/blob/master/docs/Features/Trace.md',
 | |
|     );
 | |
|   };
 | |
| 
 | |
|   render() {
 | |
|     const { stackFrames, showDocsLink } = this.state;
 | |
| 
 | |
|     if (showDocsLink) {
 | |
|       return (
 | |
|         <div style={rootStyle}>
 | |
|           To enable tracing action calls, you should set `trace` option to
 | |
|           `true` for Redux DevTools enhancer. Refer to{' '}
 | |
|           <a href="#" onClick={this.openDocs}>
 | |
|             this page
 | |
|           </a>{' '}
 | |
|           for more details.
 | |
|         </div>
 | |
|       );
 | |
|     }
 | |
| 
 | |
|     return (
 | |
|       <div style={rootStyle}>
 | |
|         <StackTrace
 | |
|           stackFrames={stackFrames}
 | |
|           errorName="N/A"
 | |
|           contextSize={3}
 | |
|           editorHandler={this.onStackLocationClicked}
 | |
|         />
 | |
|       </div>
 | |
|     );
 | |
|   }
 | |
| }
 |