Focus where i click on draftjs editor - reactjs

I have an editor made with draftjs. If I have previous content, it is filled with that content.
I need to track the clicks. When I click, for example, in the middle of the content and start writing, I will write at the beginning of the editor ... :/
How can I do that?

Your component must have been re-rendering some how when you start typing in it. You should stop that re-render or may be assign the newly got state to the Editor if it re-renders

Related

React & Canvas: changing state is breaking Canvas functions

I am trying to use a parent component to control animations in a child Canvas element. Specifically I want an animation to happen when a user inputs a correct answer.
It works until the user changes the state in the parent component, and then it no longer works.
I've made a stripped-back, minimal version of my code here to show my issue: https://codesandbox.io/s/epic-leaf-08jqvy?file=/src/App.js
My desired behaviour is that the red box bounces when a user clicks submit. That happens if they don't type anything in the input box, but as soon as you enter anything into there - changing state and re-rendering the component - the button no longer triggers the animation in the Canvas child component.
As far as I can tell, the issue is to do with changing the state when inputing text. If I make a version where the input is just assigned to a variable, it works fine, but I need to be able to use state and re-render other parts of it.
I have put a console.log in the jump() function, so I can see that it is being called, but no animation is taking place in the canvas.
I assume that what's happening is that everything is being re-rendered when the state changes, and so the useRef is no longer tracking to the right thing.
Things I've tried:
putting the canvas in a memoized component to prevent it from re-rendering
using eventlisteners to see if I can trigger the animations in other ways - keydown ones work, but I need the user to be able to type, so I tried other ones (like hashchange or audio.play) but neither of those worked.
You can see the thing I'm actually trying to build here: https://papaya-platypus-86565f.netlify.app/play Basically users answer questions and an animation plays depending on whether they're right or wrong, to give it a game-y feel.
Thanks!
I like your red box as well as your reasoning. Yes, the input state changing on keystroke is causing the entire App component to re-render. Note that your App.js component has a lot going on (all good stuff), such as your Box class instantiation, your canvas instantiation, etc.
The key is to break your components into smaller parts, particularly separating stateful components from non-stateful components. We don't want your canvas re-mounting on every input change, so we make them sibling components!
Here's a working example of your code, just in smaller components:
https://codesandbox.io/s/strange-julien-d3n4zm
I hope this helps.

When two of the same icon is present just one gets displayed

As the title says I have two icon component that supposed to display the same SVG content, however, when the second gets called, the first disappears. Not from the DOM, just from the screen...
The case is that I'm displaying a content card and a modal filled with corresponding data.
These components are sharing a content object from a separate file. What makes them displaying relevant data is an index prop.
What I figured out is nothing matters but the two icon component.
This is how an icon component looks like:
getIcon is a simple switch function returning the icon based on name.
And this is how I import the SVGs:
Does anyone can help me with this please? Thanks in advance. No console errors.
The problem seems to be hoisting.
I had the modal declared first then the content that meant to be clicked to popup the modal.
This makes no sense for me in a component based architecture on the same component level... just wanted to try if always the first icon would disappear or not.

Remove DOM Elements in React

I am trying to create a component which can be edited. It is something like this:
<div contentEditable={true}>
<OtherComponent />
</div>
I have a JSON which contains text and is rendered on the screen using this component. When I add a new paragraph in that text, DOM automatically creates a p tag with that paragraph's text. On click of save button, I save that newly added text in the JSON and call the setState method so that now the JSON can be re-rendered with the new text. On re-render, I do the see the new text, but I see it twice. Turns out, when the DOM has earlier created a p tag, React doesn't remove it on re-render. I don't want the old text to still appear on the page.
I read somewhere that when React re-renders the component (when we do setState), it only re-renders the nodes in its virtual DOM. The nodes which are created otherwise (like the p tag in my case), are not touched by React.
Is there some way I can have a solution to my problem and not see the same text twice?

Detecting click outside React component and single state for hover

I have made a navbar, which holds a searchbar, and 3 icons.
On clicking these icons, a modal is rendered.
I wanted help with two things.
Closing the modals on outside clicks!, and
The hover element is slow because it has three states, every time it is called it re-renders the code from bottom to top. I wanted the hover to have one state assigned to one parent element. But on doing that, the hover effect for all three buttons gets activated at the same time.
Code is up on : https://codesandbox.io/s/unruffled-snowflake-he95w
Please feel free to edit the code and pass me the edited fork.
I have tried handleBlur, passing an event, and eventListener.
https://codesandbox.io/s/unruffled-snowflake-he95w
Expected - Modal rendered on screen should get disappeared on clicking outside the modal.
P.S - semantic UI icons are not rendering, but they are there. They will activate if you hover over them.
Credits - SVG close icon problem solved by Drew Reese.
Ah, I see. Your ToolBar is the controlling component, i.e. the state about whether or not each toolbar item is open is stored there. You need to pass a close handler to the children components so when a "close" button is clicked it is calling the callback the parent passed in.
Here is a fork of your sandbox where I pass in an onCloseClick callback to the calendar/picker thing that simply toggles that state value back to false to close it. The picker then just assigns that callback as its onClick handler for the contaning for the close button.
You can apply the same logic to the other two components.
Note: since the icons aren't rendering for me either I added some text to the buttons so they are easier to find/see.

Can't properly force a component on-screen with scrollComponentToVisible

On a given form, we replace one component with another.
The original component is a series of TextFields, and the new form is some informational text and a button. We hide the first one, and show the second one (the UI designer has both Containers within the form).
I tried using scrollRectToVisible with various values but it didn't seem to make any difference with the scrolling.
continueButtonContainer.setHidden(false);
f.forceRevalidate();
Button continueButton =
(Button)StateMachine.GetInstance().findByName("ButtonContinue", f);
f.scrollComponentToVisible(continueButtonContainer);
f.scrollComponentToVisible(continueButton);
I'm expecting the continue button to be near the top of the screen.
If the screen was scrolled before displaying the continue button, the button ends up right at the bottom of the screen (it was below the bottom of the screen before I put in the scrollComponentToVisible line(s).
After the user scrolls the screen, the button goes up to where it needs to be, and stays there.
If the screen is not scrolled, the button appears where it should be.
I know I can probably add some invisible containers underneath the button and force them onto the screen, but I would rather have a slightly more robust solution.
There are a few issues with this. First you are using forceRevalidate which should be used in very rare cases.
Second it seems that you are invoking this on a Form, this is a bit misleading. While it seems that:
f.add(myCmp);
Adds a component to the form it is really a synonym to:
f.getContentPane().add(myCmp);
That's important because you need to invoke the scrollComponentToVisible on the scrollable container which will actually do the work and ideally be the direct parent of said component. I'm assuming it's the content pane in your case but it depends on layout etc.
The last part is letting the layout do its job. If you are invoking this before the form is showing this might not work. Notice that doing it after a call to show is meaningless as the form might take time with transitions. You can use a show listener or override the laidOut callback method to perform things like this.

Resources