This is a migrated thread and some comments may be shown as answers.

Kendo Grid column unmounts/mounts child component on re-render

5 Answers 228 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
Grid Trekkor
Top achievements
Rank 1
Grid Trekkor asked on 10 Oct 2019, 01:48 PM

Hi,

One of my grid columns uses a child component to display its own data for each row in the grid.  I have a demo here:

https://stackblitz.com/edit/react-mu6rlr?file=app/main.jsx

The issue is that any state change in the parent causes that child in the grid column to unmount re-mount.  Try opening the console at the bottom right.  Then type any text in the input.  You can see that for each state change, the child unmounts and re-mounts.

In my real app, the child is fetching data with axios.  So for each keystroke (or ANY state change), that child unmounts, remounts, and fetches the data again.  This also happens with any action on the grid, such as sorting.  Sort the grid, and the child unmounts and remounts.

How can I prevent this behavior?  I can't have the child re-fetching the data like that.

Thanks for any help.

5 Answers, 1 is accepted

Sort by
0
Stefan
Telerik team
answered on 11 Oct 2019, 06:38 AM

Hello, Grid,

Thank you for the example.

This occurs because a new function is made inside render each time the state is changed.

This can be resolved by utilizing the useMemo hook which will memorize the cell and not re-mount it every time:

https://stackblitz.com/edit/react-mu6rlr-cc837t?file=app/main.jsx

Also, if the props from the parent component have to be passed to the custom cell, we recommend using the new context API. This is an example with context:

https://stackblitz.com/edit/react-mu6rlr-ei1u9a?file=app/main.jsx

I hope one of this approaches proves helpful.

Regards,
Stefan
Progress Telerik

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Grid Trekkor
Top achievements
Rank 1
answered on 11 Oct 2019, 12:46 PM
Hi Stefan, thank you for the explanation and demo.  Much appreciated.
0
Kyle
Top achievements
Rank 1
answered on 09 Oct 2020, 04:10 PM

For all those wondering how to stop the re-render "unfocusing" in other kendo components that you are making controlled components (see Forms, Conversational UI, etc) useMemo worked!

 

Here is an example (@stefan you might want to add this to the docs for Forms and Conversational UI under the "controlled section" to help out future devs) -- this also solves the "multi line message box" but you have to wire up the send button action yourself.

```
import React, { SyntheticEvent, useMemo, useState } from 'react';
import { Button } from '@progress/kendo-react-buttons';
import { Chat, ChatMessageBoxProps } from '@progress/kendo-react-conversational-ui';
import { Editor } from '@progress/kendo-react-editor';
import { useDebouncedCallback } from 'use-debounce/lib';
import { getRawText } from '../../util/HtmlToText';

export interface MessageBoxProps extends ChatMessageBoxProps {
onChange: Function;
onSend: Function;
value?: string;
}
const MessageBox = ({ onSend, toolbarButton, onChange, value }: MessageBoxProps) => {
// Debounce callback
const [debouncedCallback] = useDebouncedCallback(onChange, 500); // helps reduce re-renders
return (
<>
{toolbarButton}
<Editor
defaultEditMode="div"
style={{ width: 'calc(100% - 100px)' }}
contentStyle={{ width: '100%' }}
onChange={e => debouncedCallback(getRawText(e.html))}
defaultContent={value}
/>
<Button onClick={onSend}>
Send
</Button>
</>
);
}
export type ChatWithEditorProps = {
onChange: (values: { [name: string]: any; }, event?: SyntheticEvent<any, Event> | undefined) => void;
data: any;
messages: any[];
};

const ChatWithEditor = ({ onChange, data, messages }: ChatWithEditorProps) => {
const [showToolbar, setShowToolbar] = useState(false);
const messageBox = useMemo(
() => (props: any) => <MessageBox {...props} onChange={text => onChange({ ...data, text })} value={data.text} />,
[]
);
return (
<Chat
width="100%"
user={{ id: data.from }}
messages={messages}
onToolbarActionExecute={() => setShowToolbar(!showToolbar)}
showToolbar={showToolbar}
placeholder="Send a message"
toolbar={
<span>
<Button icon="image" look="outline" onClick={() => console.log('toolbar btn clicked')} />
</span>
}
messageBox={messageBox}
/>
);
};
export default ChatWithEditor;
```

0
Kyle
Top achievements
Rank 1
answered on 09 Oct 2020, 04:14 PM

we lost all formatting on that paste, here is a stackblitz 

https://stackblitz.com/edit/react-mu6rlr-b3a9vn?file=app%2Fmain.tsx

 

it doesn't "work" in stack blitz, only there for formatting purposes so you can see what I did. (all in typescript, that's why it didn't work ootb in stackblitz, but I didn't spend the time to fix it)

0
Stefan
Telerik team
answered on 12 Oct 2020, 07:22 AM

Hello, Kyle,

Thank you very much for sharing the example, it is highly appreciated.

I have also added some Telerik points to your account for sharing this with the KendoReact community.

Regards,
Stefan
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

Tags
General Discussions
Asked by
Grid Trekkor
Top achievements
Rank 1
Answers by
Stefan
Telerik team
Grid Trekkor
Top achievements
Rank 1
Kyle
Top achievements
Rank 1
Share this question
or