DevExtreme React - prevent rendering widged with useState - javascript

I am developing an app in React.js based on **DevExtreme** library. I need to perform some basic actions on DevExtreme widgets (NumberInput, TextInput, Button) - all of them contains method onClick or onValueChanged that should easly give me event object with whose I can do what I want.
I am able to console their values on runtime but it is almost impossible to save their values into some hook:
```
```
const handleInput = e => {
setValue(e.value); //always causes re-render
}
When I'm clicking on this button then parent component (some DevExtreme widged) performs rerender and appears imidiatetly after few seconds.
My question is - is there a way to prevent re-rendering parent component or get event object and save it to the state without re-rendering?

Related

How to test callback methods in react functional component when the child component elements are not completely accessible

I am using jest to test my react component. However I need to test the callback methods passed as props to children components.
My component looks something like this
function myReactComp = (props) => {
onRowEditHandler = (rowData) => {
// if this then that logic
// process and trasform data
// set some local state
// dispatch action
}
return (
<ComplexDataTableComponent data={someDataProps} onRowEdit = {onRowEditHandler} />
)
}
I need to test the onRowEditHandler as a function. I want to send arguments to this function explicitly so that specific code logic are triggered.
Now many suggestions in stackOverflow says, the best way to test closure functions in react functional components is to simulate the user behavior. For example, if there is a callback for a button, find the button on the wrapper/instance and trigger the click event.
In my case, the ComplexDataTableComponent is kind of like a container, which has many children and nested components. It is next to impossible to find a specific row element, trigger its edit button and then update the form data so that the call back is triggered.
Is there any way i can get access to onRowEditHandler apart from triggering the wrapper/instance elements?

how to emulate messages/events with react useState and useContext?

I'm creating a react app with useState and useContext for state management. So far this worked like a charm, but now I've come across a feature that needs something like an event:
Let's say there is a ContentPage which renders a lot of content pieces. The user can scroll through this and read the content.
And there's also a BookmarkPage. Clicking on a bookmark opens the ContentPage and scrolls to the corresponding piece of content.
This scrolling to content is a one-time action. Ideally, I would like to have an event listener in my ContentPage that consumes ScrollTo(item) events. But react pretty much prevents all use of events. DOM events can't be caught in the virtual dom and it's not possible to create custom synthetic events.
Also, the command "open up content piece XYZ" can come from many parts in the component tree (the example doesn't completely fit what I'm trying to implement). An event that just bubbles up the tree wouldn't solve the problem.
So I guess the react way is to somehow represent this event with the app state?
I have a workaround solution but it's hacky and has a problem (which is why I'm posting this question):
export interface MessageQueue{
messages: number[],
push:(num: number)=>void,
pop:()=>number
}
const defaultMessageQueue{
messages:[],
push: (num:number) => {throw new Error("don't use default");},
pop: () => {throw new Error("don't use default");}
}
export const MessageQueueContext = React.createContext<MessageQueue>(defaultMessageQueue);
In the component I'm providing this with:
const [messages, setmessages] = useState<number[]>([]);
//...
<MessageQueueContext.Provider value={{
messages: messages,
push:(num:number)=>{
setmessages([...messages, num]);
},
pop:()=>{
if(messages.length==0)return;
const message = messages[-1];
setmessages([...messages.slice(0, -1)]);
return message;
}
}}>
Now any component that needs to send or receive messages can use the Context.
Pushing a message works as expected. The Context changes and all components that use it re-render.
But popping a message also changes the context and also causes a re-render. This second re-render is wasted since there is no reason to do it.
Is there a clean way to implement actions/messages/events in a codebase that does state management with useState and useContext?
Since you're using routing in Ionic's router (React-Router), and you navigate between two pages, you can use the URL to pass params to the page:
Define the route to have an optional path param. Something like content-page/:section?
In the ContentPage, get the param (section) using React Router's useParams. Create a useEffect with section as the only changing dependency only. On first render (or if section changes) the scroll code would be called.
const { section } = useParams();
useEffect(() => {
// the code to jump to the section
}, [section]);
I am not sure why can't you use document.dispatchEvent(new CustomEvent()) with an associated eventListener.
Also if it's a matter of scrolling you can scrollIntoView using refs

Optimize form rendering React

How can i optimize 'form' rendering. For each key pressed, the component is rendered
Any idea to solve or improve it?
const Example = () => {
const [inputForm, setInputForm] = useState('');
const inputHandler = event => {
setInputForm(event.target.value);
};
console.log('Rendering');
return (
<div>
<div>
<span>Text: {inputForm}</span>
<input value={inputForm} onChange={inputHandler} />
</div>
</div>
);
};
log of component rendering
Thanks guys!
Try to use Uncontrolled Components, from the documentation:
https://pt-br.reactjs.org/docs/uncontrolled-components.html
As #andergtk mentioned, if you want to avoid rendering the input on each key press you'll have to resort to an input that React does not control.
To write an uncontrolled component, instead of writing an event
handler for every state update, you can use a ref to get form values
from the DOM.
but the rendering on every key press that you notice is expected in the case of a controlled input where React has control over the value of the field and should not worry you
A controlled input is more "powerful" because you let React sync your data with your input value
more on this subject in the docs or in this article (there are lots of other resources on this): https://goshakkk.name/controlled-vs-uncontrolled-inputs-react/
improving your case is not about stop rendering, every time input value is changed it needs to be re-rendered, if not changes wouldn't apply
to improve performance you may:
useCallback to the event handler if you gonna do calculations there
maybe split label out of the component returning only input element
useState may be declared outside Input component to make sense
Input props: { value, setValue } ,. then setup callback
react renders its components based on props or state changes, so always something changes on screen react has to re-render that component

reactjs) how can i keep current input value of component when re-render?

I developing front-end with reactjs recently.
but i have a problem in my SPA project.
my webapp have tab menu like a text-editor.
I want each tab to always keep their input value. However, these values are lost because tabs are re-rendering when they disappear or are new.
Is there a way to keep these values without using storage like local-storage?
You will need to take advantage of the useState hook to store an object that contains the data from your tabs... so you can get the data from the object whenever the state changes... assuming you don't update it wrongly.
Find illustratio below:
import React, { useState } from 'react'
function MyTabComponent (props){
const [tabData, updateTabData] = useState({})
return(
// your component jsx here
// you can then fetch your tab data from the tabData object
)
}
Hoping you find this helpful.

React Native - Refresh top component

I set up a NativeEventEmitter and added a listener to it in my React Native app outside of any Component in index.ios.js. The listener's callback method modifies the app's global dict of localized strings which are used throughout the app's UI. I've used the ReactNativeLocalization library to display localized strings.
I need the callback to somehow refresh the UI to display the new strings, regardless of which components are currently on screen.
Here is the code for my listener:
global.localizedStrings = new LocalizedStrings({});
const myModuleEvt = new NativeEventEmitter(NativeModules.StringsEmitter);
myModuleEvt.addListener( 'LocalizedStringsUpdated', (newStrings) => {
localizedStrings = new LocalizedStrings(newStrings);
// TODO force update current screen
});
Any ideas how that could be achieved? Thanks

Categories