multiple depth exceeded in react hooks - reactjs

I am trying to create multiple selection of shapes using transformer of react konva. I want to pass multiple nodes to Transformer. while doing this, i am getting multiple depth exceedederror. i am using a shape ref from the child component and setting it's value. It is with React hooks.
I've commented the setNodes(temp) line. works fine without this. but i want to set it to setNodes.
Here is the demo sandbox link.

You are making infinite loop in this line:
onClick={onSelect(shapeRef)}
Probably you need this instead:
onClick={() => onSelect(shapeRef)}

Related

How to know deep inside component hierarchy we have a special component, efficiently?

I'm creating a form builder using React.
The point is, everything is dynamic.
A form can have fields, or field groups. Each field group can have many fields. Each field can have it's own controls, hints, valdiations, etc.
This means that a form is a component hierarchy. A tree of components.
Now I want to know if in this tree, any Upload field exist at all.
Because if there is no Upload field, then I submit the form using application/json content type. Otherwise I would submit the form using application/form-data content type.
I know I can traverse the entire JSON of component props. But that seems very inefficient.
Is there a way to traverse React's component tree in an efficient way?
You can do so by using contextApi or with its hook for React Version > 16.8 the useContext.
Read more in React official docs
My suggestion is to use formik npm package to build your form correctly and easily, formik using context for managing the state behind the scene. I recommend it for regular use of forms, not heavy form with many fields (~25-30 max) like in enterprises.
You can read about formik more here:
https://formik.org/docs/api/formik
There is another alternative for formik which is also popular in react using forms:
react form hook: https://react-hook-form.com/
I didn't use it yet but as I know it has some pros/cons over formik.
Easiest way is vanilla JS.
const FORM_SELECTOR = '#some-form-id';
const UPLOAD_SELECTOR = '.some-upload-class';
const form = document.querySelector(FORM_SELECTOR)
if(form.querySelectorAll(UPLOAD_SELECTOR).length) {
// upload exists
} else {
// upload does not exist
}

How to sync two counters in React js using hooks?

I am new to react js,
I want to connect two counters in React js, As if one counter value gets increased by one the other counter value should get decreased by one, And on the button click, I need to add a new set of counter pairs. Can anyone suggest to me a solution? Thank you.
If you want to create a counter pair and have to do it multiple times, I would suggest to use custom Hooks.
I have created one for the purpose named useCounter.
Here you have to pass an array of length 2 if initial state of counter.
And the hook will return [couters, updateCounter, err] the array.
You can refer to this code for insight.
Hook: https://codesandbox.io/s/happy-swartz-ikqdn?file=/src/counterHook.js
Component using hook: https://codesandbox.io/s/happy-swartz-ikqdn?file=/src/pair.js
Note: goto https://ikqdn.csb.app/pair in codesandbox browser

Ag grid using framework cell renderer keeps re-rendering on any store change

Trying to implement a custom cell framework renderer with React and it seems simple enough. Create the React component, register it with frameworkComponents.
The data that populates rowData is coming from my redux store. The custom cell renderer is a functional react component.
The issue is that because I'm using a frameworkComponent - a React component in my case - as a cellRenderer, it seems that any change in the data for the grid the I'm getting via useSelector(selectorForMyData) causes a re-render of my frameworkComponent, which on the browser, looks like a random, annoying flicker. The application is heavily wired into redux
Two questions:
1 - How come when I natively use ag grid to render this cell using a AgGridColumn without any custom cell renderers, it doesn't cause this re-rendering behavior on the same store changes? I have a click event bound to the main page that toggles a flag to false (in the case a snackbar alert was open).
2 - Is there any way to get around this? I've tried wrapping my return statement in the framework cell renderer component with a useMemo with the params as a dependency, but that doesn't seem to work. Also tried making a render function via useCallback with the same idea as useMemo and that doesn't help either :/
Thanks
pseudo-code for situation:
App.tsx:
<MyAgGrid/>
MyAgrid.tsx:
const MyAgGrid = () => {
const data = useSelector(selectorForData);
return (
<AgGridReact
rowData={data}
frameworkComponents={
{'myCustomRenderer': CustomRendererComponent}
}
columnDefs={
['field': 'aField', cellRenderer: 'myCustomRenderer']
} />
);
};
CustomCellRendererComponent.tsx:
const CustomCellRendererComponent = (params) => {
console.log("params", params) //logs on every redux store update
return (
<div>HELLO WORLD</div>
);
};
The cells that are rendered via the CustomCellRendererComponent are re-rendered on any redux store change. I'm guessing it's due to useSelector causing the re-render on store changes, which is expected, but then it doesn't answer my first question.
EDIT:
I went "function as class" route shown here ("MyCellRenderer") and so far am not seeing the re-rendering issue, so I will stick with that for now even though it's god ugly. This leads me to believe my issue is trying to fit a React component/hooks, with its lifecycle nuances, as a cell renderer is causing problems. Still, I feel like there should be a way to prevent the behavior of constant re-rendering, otherwise it's a pretty useless feature
EDIT pt 2:
I dug deeper and while I haven't found an out of the box solution for it, I added the reselect library to memoize some of my selectors. The selector I use to get rowData is now memoized, and I'm no longer seeing this issue. Will mark as answer in a few days if no one provides a better, ideally out of the box (with redux or ag grid), solution for it.
As I stated in one of my edits. I figured it out, kind of.
I added the library reselect to the application, and it fixes the symptoms and I'm content with it going forward. It allows you to memoize your selectors, so that it only registers changes/"fires" (leading to a re-render) only if the any of the dependency selectors you hook it into changes/fires, so now, my grid doesn't "flicker" until the actual row data changes since my selectorForRowData is memoized!
I'm still uncertain why prior to using a frameworkComponent (React Component) as a cell renderer I wasn't seeing the symptoms, but I'm happy to just assume Ag-Grid has a lot of performance tricks that clients may lose when plugging in their own custom functionality, as is the case in a custom cell renderer.

Use form.getFieldValue to add logic between field without warning

I have a Ant Design 4.x.x Form element without multiple Form.Item. I need to implement some logic involving form items' values, for example disabling a field if another one's value equals something, or recalculate select options when a text input changes.
To do so, I create the form using Form.useForm() and use form.getFieldValue() in my functional component body and / or in the returned JSX, like so :
It is working as I expect to, but at startup, getFieldValue usages throw annoying
index.js:1 Warning: Instance created by `useForm` is not connect to any Form element. Forget to pass `form` prop?
I found that Form functions cannot be used before rendering, and the problem also occured when displaying a form in a Modal like stated in the docs.
So I feel that I'm missing something on how to correctly add custom logic between fields, or doing some calculation involving fields values in component body.
What would be a correct approach to do this ?
Try adding getContainer={false}, to your modal this will work for you.

Search function using filter and hooks

I am trying to follow an react-course on udemy but am using hooks instead of classes and states as the instructor shows. It is an simple app where I download random userinfo and images and shows them using flash-cards.
Then I need to be able to search/filter the users. I have managed to get this working by using two different useEffects but I would like to know if this is the correct way to solve this. And also if I can get any tips on how to improve my current code.
Project on codesandbox
It's OK. However you don't need to use the second useEffect. you can compute filter directly in the functions body. If you want to cache the results you can use useMemo hook but it's unnecessary here.
Basically what I would do is:
const filter = users && users.length ? users.filter((person) =>
person.name.toLowerCase().includes(searchField.toLowerCase())
); || []

Resources