When I used to program with python I could run a python app and then execute methods and access variables of the app from within terminal. This was a great way to test things around.
Working on my JS app I often use console.log to try things out but I am looking for a way to try things without having to rerun the app each time. I want to be able to call any method / variable of my React app (including imported classes etc) from within console "at run-time".
Is this possible? If yes, how?
If not, what is the best alternative to switching between code and browser back-and-force to see the effect of certain changes console.log ?
Context
I'm trying to debug a React application but cannot modify the source code to log redux variables. In chrome I'm able to access the redux store via the associated extension but it seems no such equivalent exists for safari.
Question
How can I access the redux store in Safari? Can I do so using the console?
The simplest solution, unfortunately, is to modify the source code to set a global variable to the Redux store. (It may be worth preemptively modifying any applications you can control to do this, just to make Safari easier to debug.)
Without modifying the source code, it should be possible, although it's awkward. The following instructions work for React 16.12.0.
In Safari's Web Inspector (dev tools), go to the Elements tab and find your React root element (the <div id="root"> or similar that you pass to ReactDOM.render).
Click on it. Web Inspector should show a = $0 next to it, indicating that you can now reference that DOM node in the Web Inspector console as $0.
In the Web Inspector's Console tab, type Object.keys($0) and press Enter to see the internal properties that React adds to the DOM node. For my app, I see ["__reactContainere$8yexuoe6iiv", "_reactRootContainer"].
Dump the internal React object to the console by typing $0["__reactContainere$8yexuoe6iiv"] (substituting your internal property name) and pressing Enter.
Inspect the object properties to find the Redux store: on my app, it's under child, under memoizedProps, under store, but this may depend on the specifics of your React component hierarchy and where and how you mount Redux's <Provider>.
Use the store reference you just found to call Redux's getState. For my app, that means typing $0["__reactContainere$8yexuoe6iiv"].child.memoizedProps.store.getState() and pressing Enter.
A simpler one-line alternative to the above:
document.getElementById('root')['_reactRootContainer']._internalRoot.current.child.memoizedProps.store.getState()
In case you are using Nextjs framework, you can achieve this by opening the console in safari. Type window in it. Expand it. Now just check in the window object property. You will find a key something like '__REDUX' or something like that. In my case it was __NEXT_REDUX_STORE__.
Now after you find it just enter the following in your console.:
__NEXT_REDUX_STORE__.getState();
you can now check your current redux state of your application.
I'm not aware of a safari extension for redux debugging (corrections welcome). This thread suggests that it's due to a lack of a dev-tools API: https://github.com/zalmoxisus/redux-devtools-extension/issues/435
Redux state isn't in the global scope, so you won't be able to access it through the console without modifying the source code.
You could just extract state using the connect function. Then just stringify it?
<pre>JSON.stringify({this.props.store, null, 2})</pre>
Then you could visually see it.
Adding to #josh-kelley's answer...
In 2021, tested with Safari Version 12.1 (14607.1.40.1.4), following line did the trick for me:
document.getElementById('root')['_reactRootContainer']
._internalRoot.current.child.memoizedProps
.children.props.store.getState()
Notice the children.props difference from what #josh had mentioned.
According to its GitHub repository for other browsers use remote-redux-devtools.
So for my sins I'm on an Angular 2 project. I use angular.element($0).scope() all the time on my old Angular 1 work to inspect an element and see what's on the scope at that point in the dev tools. This is super useful, is there something similar in Angular 2?
Augury is a great suggestion. If you want direct access use
ng.probe($0)
See also
Get ComponentRef from DOM element
How to access the *angular 2* components' data in the browser's console?
how to access Angular2 component specific data in console?
Have you tried using Augury? Link: https://github.com/rangle/augury
Hi i am currently working on a firefox Addon-sdk and i would like to know if there is a way to import JS files which uses DOM objects(like window) into the main.js code. I did use "mozIJSSubScriptLoader" but the addon keeps returning all the dom objects defined in the loaded scripts as "NOT DEFINED" and i think this should be because the main.js code does not have access to the DOM. Please, let me know if there is any other way to import/load these js files. Thanks in advance.
You can get access to a window like this:
const { getMostRecentBrowserWindow } = require('sdk/window/utils');
var aXULBrowser = getMostRecentBrowserWindow();
or you can enumerate through them all, that should be something in sdk/window/utils called "somethingEnumerateSomething"
Based on your comments in my other solution posted in this topic:
Posting as separate answer as I think the solution is totally different. If this is the right answer Ill delete my previous solution.
Check out the following:
Services.scriptloader.loadSubScript(uri.spec, global);
MDN :: mozIJSSubScriptLoader
Components.utils.import
Example showing how to use it, and that in bootstrap you can only import in or after your startup function: GitHubGIST :: Noitidart / _template-BootstrapJSM.xpi
MDN :: Components.utils.import
I'm writing an e2e test suite using Protractor.
I know it's built on top of WebdriverJS, and I'm trying to using some webdriverJS functionality.
Namely, I'm trying to enqueue some behavior using the webdriverJS' promise manager, and the WebdriverJS documentation says I should use
webdriver.promise.controlFlow().execute(function myBehavior(){...});
Trouble is, I don't know how to access that "webdriver" object. There is no global variable named "webdriver".
Can someone help me on this?
EDIT:
Now that the question has been solved, I'd like to highlight the fact that one must use
browser.driver.controlFlow()
and not
browser.driver.promise.controlFlow()
despite what WebdriverJS documentation may suggest.
The documentation says browser.driver is the underlying webdriver.
So can you try this:
browser.driver.controlFlow().execute(function myBehavior(){...});