I'm trying to create my custom devtools for a high-level protocol renderer based on React now, so I'm learning how popular framework's devtools work, and I try to read the code of react-devtools and vue-devtools, have a basic understanding of how they work, but I still have a lot of questions:
Vue: I guess Vue set __vnode and __vueParentComponent as the dom Properties, and vue-devtools get Vue vm info by access dom properties.I don't read the code carefully, so I dont know how they pass the change of component tree, incremental update or full update, but I guess the __vnode is enough to rebuild the componentTree.
React: react-devtools is hard to read, I guess react send every change in react-reconciler, and rebuild the componentTree by these commits.I found there're some dom properties like __reactProps$... or __reactFiber$... in react, but I don't think they work in react-devtools.
preact: I dont read much code of it, I guess it just hook the class of Component and Fragment in Preact.
I‘m wondering which way is better to build my devtools, and It'll be very helpful If someone can give me more details or articles about these devtools
Related
I am using nextjs along with tailwind css and a bunch of other libraries like web3uikit.
the app work totally fine but as soon as I import ConnectButton from web3uikit and use it in the sidebar component, it gives me the following error:
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
Here's the link to the github repo, just cloning and install the dependencies would help you in setting up the project and then npm run dev.
Link: https://github.com/oneknucklehead/marketplace-web3
I believe it is a server-side rendering issue! A screenshot of how I got the <ConnectButton /> to render in a nextjs application is below:
Implementing the ConnectButton Component Screenshot
When the error popped up saying I had an invalid hook call, I closed the error box and the button was rendered in and when I click on it, it showed the web3Modal with the proper sign-in options. I thought that maybe it was a server-side issue
So I fixed it by using a useState hook with a boolean value as seen in the screenshot. It is false by default but will only become true when the component loads in(used a useEffect hook to implement) and I take advantage of that via conditional rendering which is also shown in the screenshot. Once I did that, I haven't encountered the issue at all! Hope this helps!
Go to node_modules -> web3uikit-> node_modules and delete the react folder under it.
web3uikit node module has a version of react pre-installed with it. Apparently, that's causing errors. Now, why does deleting the folder fix the error? Honestly, I don't know, but it removed the error. This answer is from someone named David MacDonald.
After the page load the changes to the store are not being captured by the react, but if i make any changes to the any of the reducer files after a live-reload the entire page starts working, but if i reload the page the becomes the same and store updates stop being rendered.
i have tried a lot of things already, diffrent store configuarations, different methods of getting store values namely connect and useSelector.
i have checked dispatch and stores with logs they are working fine, selectors seem not be the issue as well.
I have wasted more than 4 hours on something that i was supposed to take 30mins, any help would be nice to catch whatever i am missing.
link to code sandbox sample here, https://codesandbox.io/s/confident-oskar-30ow2z?file=/src/App.js
there appears to be some issue with using StrictMode and ReactDOMClient.createRoot. Perhaps you could remove the strict mode in index.js or just use ReactDOM.render. I tried with your sandbox removing the strict mode and it appears to be working fine.
Here is the updated sandbox -
https://codesandbox.io/s/modern-sun-6u5icq?file=/src/index.js
I have an existing application in which I've encountered a problem.
The root of the problem, as far as I know, lies in a broken Apollo query (for example, when trying to spread data whilest it's still undefined). This leads to a wierd UI, in which there are humongous icons and to a warning of such kind:
Warning: Prop className did not match. Server: "MuiSvgIcon-root-69" Client: "MuiSvgIcon-root"
After some research, I found out that the reason of this may be the disableGeneration prop which should be set to true for performance reasons, but I also suspect that if it's turned on then MUI skips the className generation and yields correct classnames as the result.
The question is: what is the correct way to use it, or is there any other way to fix this issue? My stacks is as follows:
next.js 9.1.1
material UI 4.6.0
react-apollo 3.1.2
I have tried several combinations of using StylesProvider and ServerStyleSheets, though I haven't managed to get the job done. Currently I'm using this in _document.js:
const sheets = new ServerStyleSheets({
injectFirst: true
});
And this is the way I use getDataFromTree, though it looks quite odd to me:
const sheets = new ServerStyleSheets({
disableGeneration: true
});
await getDataFromTree(sheets.collect(<AppTree {...appProps} />));
I had done a lot of googling but couldn't find a concise result of how to use SSR with Apollo & Material. Any help would be much appreciated :)
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.
I'm taking a foray into Firefox extension development for the first time, and so far it's been pretty comfortable going, but I'm running into a problem; one of the things I need to do overwriting the built-in nsIPromptService and replacing it with something of my own instead.
I walked through the basic XPCOM component creation tutorial here and got the hello world one working:
https://developer.mozilla.org/en/creating_xpcom_components
And everything in that seems to work fine, but nothing I've been able to find or research shows how I can overwrite an interface from javascript. I've seen things in C++ and Java that seem to be able to overwrite the built-in components, but I can't find anything about doing this from javascript, and just trying to change the contract ID didn't work; when I try to get the service from the contract ID (as below), it just returns the original, built-in component version.
var myComponent = Components.classes['#mozilla.org/embedcomp/prompt-service;1']
.getService(Components.interfaces.nsIPromptService);
Is there something really obvious here that I'm missing? Is this the wrong way to go about overriding components (I can't seem to find anything anywhere, so I'm not really sure what I should be doing..).
Neil, thanks for the suggestion. That's what I thought I was doing (and I was), but if you're actually overriding a contract (instead of defining a new one), it looks like the answer is that you have to go to the nsIComponentRegistrar and actually register your factory (rather than relying on the chrome.manifest to handle it for you). An example of this would be:
Components.manager.nsIComponentRegistrar.registerFactory(CLASS_ID, CLASS_NAME, CONTRACT_ID, MyPromptServiceFactory);
Where the constans were:
const CLASS_ID = Components.ID("{a2112d6a-0e28-421f-b46a-25c0b308cbd0}");
// description
const CLASS_NAME = "My Prompt Service";
// textual unique identifier
const CONTRACT_ID = "#mozilla.org/embedcomp/prompt-service;1";
Where the CLASS_ID/CONTRACT_ID were the IDs for the pre-existing service.
You need to register your component using the contract id of the service that you want to override.