I'm struggling to figure out how to make a single toolbar work across multiple editors - Only the current editor in focus should be effected by the toolbar. Is this possible? Is there a good example out there for Draft.js?
What you can do is:
It is good to have global state in use for this case
(for React hooks)
Pass your toolbar the state and setState for your editor.
When you focus on editor dispatch the state and setState for that editor to global state and make Toolbar subscribe to it.
also for the editor whenever state changes, you need to update the global state as well.
by this you will achieve managing editors from one toolbar.
I recommend you to not use Redux Toolkit as your global state library. Because when you will try to save the state it will throw an error (EditorState is nonserializable).
Related
I have the following issue:
I would like to create a simple choropleth map using react-leaflet's GeoJSON component. I also want to have a tooltip that shows a value on hover over a GeoJSON feature. The problem is performance. A CodePen example can be found here: https://codepen.io/timester-the-typescripter/pen/gOXGKOY
I attach event handlers to each GeoJSON feature and set a state variable in my "main" component that holds the value for the currently hovered area.
const [selected, setSelected] = React.useState(null);
My tooltip relies on that state variable to show its value. Because every mouse hover event causes main component state change, the GeoJSON component gets re-rendered all the time. This is not a huge problem in the CodePen example, but for a full world map it is unfortunately.
I assume that the state change causes this because if I comment out the 2 setSelected lines (line 55, and line 67 in CodePen), the re-renders (calls to createGeoJSON ) stop, and the event handlers run a lot faster as the profiler pictures show below.
Mouseout event with state change:
Mouseout event with state change commented out:
I tried many solutions with no success. For example I think I can't memoize the GeoJSON component because the Tooltip must be its child and that depends on the state of the main component.
In the future I want to add more components depending on the hovered state variable like a legend, etc.. and maybe that variable will be a bit more complex than a simple number too.
What options do I have here? I had another stackowerflow question about this, but then I did not understand the problem completely, so it was not super focused. I'm at the point where I'm thinking about rewriting it in Angular. I found react and react-leaflet very pleasant to work with, until this issue came up.
The problem is that currently you are recreating the map with the appropriate Tooltip on each mouseover via the state. Instead, you should bind all Tooltips at map creation with layer.bindTooltip(). This will allow you to just show/hide them without having to recreate the map again, since they are already created and their creation will not rely on state.
See this github issue for an example with Popups (but the logic for Tooltips should be the same): https://github.com/PaulLeCam/react-leaflet/issues/33
I got help from this reddit comment https://www.reddit.com/r/reactjs/comments/std46f/comment/hx3yq34/?utm_source=share&utm_medium=web2x&context=3
The solution I applied based on this is not to use the Tooltip as a child component, but bind a tooltip to each layer in the onEachFeature method.
const onEachFeature = useCallback((feature, layer) => {
layer.bindTooltip(feature.properties.COUNT, {sticky: true});
...
This way I could also wrap the GeoJSON component in a useMemo() as there were no longer dependencies on the selected state. I also wrapped the style and onEachFeature functions in useCallback().
This combination solved the issue!
I create 2 Text Boxes one with hook and the another one with the old style, now in Hook mode when the user input change the textbox value the whole page rendered, but with old style there only the text-box rendered not the whole page, if you have the complex page with many objects like (Data Table, form, buttons, inputs, etc..) the single change on one of these components forced to re-render everything and it decease performance, for example typing in the text-box take time to effect on page and the delay time is more than user typing speed.
the one workaround solution is using the callbacks and useMem but if the page is complex(lots of objects as described, and all of these objects has many properties the callback and useMem is very very complicated to handle single object property.
SandBox Example
This is exactly how react hooks should work. what will cause a rerender in react? two things:
change in props
change in hooks or say in a better way hooks state
in the second case, the useInput state is changing so that causes a rerender and it's absolutely normal behavior. I think using custom hook in that way is not a good practice.
I recommend reading this article for more information on react rendering: https://www.codebeast.dev/usestate-vs-useref-re-render-or-not/
I am looking for a good code pattern to allow some communication between components, when using React & Redux.
Most likely this communication should be done via redux, like many articles suggest. (like this one, for example).
However, there are some situations when using the store would be a bit of a hack rather then using it for state management. These special cases are usually when you need to give a command to a component, like show or hide.
I will give an example:
Lets say that we have a <Tooltip /> component which all it does is render some help icon, that when clicked, opens a tooltip popup.
And lets say that we have more than one in a page, but we want to make sure that only one is open at a given time. So if tooltip A is open, and the user clicks on tooltip B, then B should open and A should close.
Here are some patterns that I thought might be relevant to implement this requirement:
Using Redux: We could have in the store some state for these tooltips:
{
showTooltip: "A" // the ID of the tooltip to show
}
This means that we have to connect the tooltips to the redux store, and check for each tooltip if it's ID is the one that should be opened, and when the user clicks on the tooltip icon, we dispatch an action to set the opened tooltip.
Using additional event mechanism: We can use an additional event mechanism to Redux, like emitter.
In this case we can fire an event whenever a tooltip is about to be opened, and all other tooltips can listen and hide themselves once they get such an event.
I have to say that it seems to me that maybe having two event mechanisms in the app seems a bit redundant, but on the other hand, using redux store to communicate with components seems a bit overkill.
Would love to hear some opinions about this issue.
The React and Redux world generally encourages representing your app's behavior as state. For example, rather than an imperative $("#someModal").show() command, you might save a flag value somewhere that says {modalVisible : true}.
There's numerous examples of using state to drive modals and popups. A typical implementation would store the values for a single modal or a list of modals in state somewhere (either in a parent component or in Redux), and then render modal components as appropriate based on those values, such as: {type : "notificationPopup", level : "warning", message : "Something happened!"}. The basic approach works whether you're storing the data in React, Redux, MobX, or something else.
For specific examples, see Dan Abramov's answer to "How can I display a modal dialog in Redux?", Dave Ceddia's article "Modal Dialogs in React", the article "Scalable Modals with React and Redux". I also have other articles that demonstrate modal management in the React Component Patterns#Modal Dialogs and Redux Techniques#UI and Widget Implementations sections of my React/Redux links list.
I have a Tooltip component that when hovered displays a simple tooltip.
When you mouseLeave the component, a setTimeout fires, and when it ends, the tooltip is closed (setState({ open: false })).
Now I'd like to add a behavior to reflect the one of the native OS tooltips:
When you mouseLeave a tooltip, but instantly mouseEnter a different tooltip, the previous tooltip is instantly closed, and the new one gets opened.
To do so, I need to have a shared state between all the instances of Tooltip component. I could use Redux but it seems a bit overkill for a so simple task (I'd need a container that interacts with the store and makes an action and a property available).
Are there simpler solutions?
The best way to share information between ReactComponent is the Flux architecture. Redux is one of them.
A more simple option is to use the browser native storage used to store temporary information : it is similar to global variable but with particular scope and duration definitions.
Move the shared state into the state of the parent component of all Tooltips, have this parent define a method setWhatever to set the value, and pass this method to Tooltip components via a property. This way, children can call their setWhatever property, which is really the one of their parent, when they need to change the state.
According to the docs, one should avoid having multiple components with state. I am in the situation where I want to make a text box that automatically expands vertically as the user writes, and for that I'm using this trick http://www.impressivewebs.com/textarea-auto-resize/, which means I need to get the height of a component. Now, I've been playing around with it a bit, and it doesn't seem feasible to pass a ref to my parent component which contains state, so the easy way out would be to keep a piece of state in the component with the textbox, and then use the ref from there.
This got me thinking, how exactly do multiple state components negatively affect my app? Is it only maintainability / comprehensability? Or are there actual performance issues with it? I've noticed a lot of open source react components that you would just plug in to your app keep state, meaning if you use open source components, chances are you will have several state components in your app.
It's totally ok to use local state for this kind of tricks on DOM. It's even better approach, than to share such implementation details to parent components.
In general, use this places for state:
Application-wide data in stores outside React (redux, flux-store, observables)
Form temporary data can be placed in store also. But if don't need it anywhere else except form, it's better to place this data in form component.
Tricks on DOM, short living and very local state can be placed in component that just need it
are there actual performance issues with it?
No. If you'll place all your state in components, your application will become even faster. Because when you update local state, only this component and it's childs updates.
But you shouldn't do that, because it kills maintainability.
lot of open source react components that you would just plug in to your app keep state
If component doesn't allow you to control it through the props - it's bad component. Usually open source components written to be easier to use, so they provide nice defaults, that allow you to just place component to your application, and be happy with that.
For example, Tabs component usually controlls selected tab using local state. But also it takes selectedTab and callback onSelect, so you can control it by yourself.
Stupid components (like your textarea component) should not have state with data. But they can have their own UI state.
In this case you can easily keep textarea height in state of stupid component.