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

React Grid + Rest + Hooks + Graph QL?

10 Answers 523 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
Robert
Top achievements
Rank 1
Robert asked on 17 Jun 2019, 07:10 PM

Hi,

I'm struggling to wire up a grid to an existing restful service using hooks (rather than classes, as the examples do). The closest I have gotten is wrap the grid jsx in a conditional, based on the data load; which to me is a bit ugly. Seems like I should be able to watch the data and update as needed.

Looking forward, I'd like to swap to GraphQL.

The problem is, I am having a hell of a time finding examples on any of this. Everything in the docs is pre-hooks, oData based. As we are running MEAN stack, oData is out of the picture for us.

10 Answers, 1 is accepted

Sort by
0
Robert
Top achievements
Rank 1
answered on 17 Jun 2019, 07:50 PM

By way of example, the following code is ignoring the column config (and this is the previously  mentioned conditional):

const Logging = () => {
 
    const [data, setData] = useState([]);
 
    useEffect(() => {
        const fetchLogs = async () => {
            await getLogs()
                .then((logs) => loadLogs(logs));
        };
        fetchLogs();
    }, []);
 
    const loadLogs = (logs) => {
        setData(logs);
    };
 
    return (
        <>
            {data.length ? (
                <>
                    <Grid
                        style={{ height: '420px' }}
                        sortable
                        data={data}
                        total={data.length}
                    />
                    <GridColumn field="app_id" title="app id" />
                    <GridColumn field="app_name" title="app name" />
                    <GridColumn field="app_version" title="version" />
                    <GridColumn field="created_on" title="created" format="{0:d}" />
                    <GridColumn field="id" title="id" />
                    <GridColumn field="message" title="message" />
                    <GridColumn field="type" title="type" />
                    <GridColumn field="updated_on" title="updated" format="{0:d}" />
                </>
            ) : null}
        </>
    );
};
0
Accepted
Stefan
Telerik team
answered on 18 Jun 2019, 12:47 PM
Hello, Robert,

Currently, we have separate examples with hooks and with GraphQL, but they are separate ones:

1) Hooks:

https://www.telerik.com/kendo-react-ui/components/integration/nextjs/

2) GraphQL:

 - Grid with editing:

https://www.telerik.com/kendo-react-ui/components/integration/graphql/

- Homepage demo:

https://github.com/telerik/kendo-react-homepage-demo/

If these example do not prove helpful, please let me know and I will try to create a small example with KendoReact Grid using hooks and GraphQL.

-----------------------------------------------

As a side note, our new documentation site is written with GatsbyJS, GraphQL,  hooks and our components work nice in this stack.

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
Robert
Top achievements
Rank 1
answered on 18 Jun 2019, 01:51 PM

Hi Stefan, 

thanks for the reply. It turns out, I was making a pretty simple error. If you note the markup in my code example, I was not nesting the <GridColumn> in the <Grid>; once I made that change, everything was working perfectly.

The thing is, I was getting no errors and no feedback, so I kept looking elsewhere for the issue and assumed it might have something to do with how I was trying to bind the data. I'm pretty new to both React and Kendo so this was a novice mistake :)

0
Robert
Top achievements
Rank 1
answered on 21 Jun 2019, 07:58 PM

Hi Stefan, 

I have progressed on and now am using GraphQL, Hooks and Apollo. I was able to connect it quiet easily to the data, but now I am floundering on enabling paging/sorting, etc.

My query (through Apollo) looks like this:

const LOGS_QUERY = gql`
    query Logs($skip: Int, $first: Int) {
        logs (skip: $skip, first: $first) {
            id,
            app_id,
            app_name,
            app_version,
            type,
            message,
            created_on,
            updated_on
        }
    }
`;

 

 

 

0
Stefan
Telerik team
answered on 24 Jun 2019, 04:49 AM
Hello, Robert,

Thank you for the code.

This can be achived by usitizing the onDataStateChange or the onPageChange(if the Grid has only paging) events:

https://www.telerik.com/kendo-react-ui/components/grid/api/GridProps/#toc-ondatastatechange

https://www.telerik.com/kendo-react-ui/components/grid/api/GridProps/#toc-onpagechange

These events will contain the needed information for the request, skip and take. 

Then the requested data from the request has to be passed to the Grid.

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
Robert
Top achievements
Rank 1
answered on 24 Jun 2019, 02:10 PM

Thanks for the response Stephan,

I did try to use both of those event hooks, in many different setups, but haven't had any success. It seems that wrapping the <Grid> component with the Apollo <Query> component, is break things. Doing this, I am not able to get the pageChange event to fire.

I'd prefer to use the Apollo library, as it is quite popular and easy to use. This is my first time using React + GraphQL + Kendo, any suggestions?

   const pageChange = (e) => {
        console.log(e); // this never fires!
    };
 
    return (
        <Query
            query={LOGS_QUERY}
            variables={{
                skip: 0,
                first: 5
            }}
            fetchPolicy="cache-and-network"
            notifyOnNetworkStatusChange={true}
        >
            {({ loading, data, fetchMore }) => (
                loading
                    ? <Spinner />
                    : <Grid
                        className="logs mt-4"
                        data={data.logs || []}
                        pageable
                        sortable
                        onPageChange={pageChange}
                    >
                        <GridColumn field="app_id" title="App Id" />
                        <GridColumn field="app_name" title="App Name" />
                        <GridColumn field="type" title="Message Type" />
                        <GridColumn field="message" cell={MessageCell} title="Message" />
                        <GridColumn field="created_on" cell={DateCell} title="Created" />
                        <GridColumn field="updated_on" cell={DateCell} title="Updated" />
                    </Grid>
            )}
        </Query>
    )
};

 

0
Robert
Top achievements
Rank 1
answered on 24 Jun 2019, 05:39 PM

Stefan,

const Logging = () => {
 
    const [dataState, setDataState] = useState({ skip: 0, take: 10 });
 
    /**
     * Grid dataStateChange Event Curry
     * - curry the fetchMore function for future consumption
     * @param {*} fetchMore - Apollo paging fetch function
     * @return {function} - dataStateChange Event handler
     */
    const dataStateChangeCurry = (fetchMore) => {
         
        /**
         * Grid dataStateChange Event handler
         * @param {Event} e - dataStateChange Event
         * @return {Promise} - curried function fetchMore Promise
         */
        const dataStateChange = (e) => {
            setDataState(e.data); // update the dataState with e.skip/take
            return fetchMore({
                variables: {
                    skip: e.data.skip,
                    first: e.data.take
                },
                updateQuery: (prev, { fetchMoreResult }) => {
                    return fetchMoreResult
                        ? Object.assign({}, {
                            logs: [...fetchMoreResult.logs]
                        })
                        : prev;
                }
            });
        };
 
        return dataStateChange;
    };
 
    return (
        <Query
            query={LOGS_QUERY}
            variables={{
                skip: 0,
                first: 10
            }}
            fetchPolicy="cache-and-network"
            notifyOnNetworkStatusChange={true}
        >
            {({ loading, data, fetchMore }) => (
                <React.Fragment>
                    <Grid
                        className="logs mt-4"
                        data={data.logs || []}
                        total={30}
                        pageable
                        sortable
                        {...dataState}
                        onDataStateChange={dataStateChangeCurry(fetchMore)}
                    >
                        <GridColumn field="app_id" title="App Id" />
                        <GridColumn field="app_name" title="App Name" />
                        <GridColumn field="type" title="Message Type" />
                        <GridColumn field="message" cell={MessageCell} title="Message" />
                        <GridColumn field="created_on" cell={DateCell} title="Created" />
                        <GridColumn field="updated_on" cell={DateCell} title="Updated" />
                    </Grid>
                    {loading && <Spinner />}
                </React.Fragment>
            )}
        </Query>
    )
};

I was finally able to get the paging working. Please take a look and point out any obvious issues you might see.

Thanks in advance!

0
Stefan
Telerik team
answered on 25 Jun 2019, 06:12 AM
Hello, Robert,

I'm glad to hear that the paging is working successfully.

Based on the provided code everything regarding the Grid seems correct.

The only thing that I noticed is that the total is set to a fix number(30). When the data is coming from the server we recommend to get that value from the server as well, as the total on the server may be different.

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
1
Robert
Top achievements
Rank 1
answered on 25 Jun 2019, 01:41 PM

Thanks Stefan,

I should have mentioned that. We didn't have total's coming through yet, so I was just hard-coding while developing. I will update that, of course, when the totals is available.

BTW, I ended up stumbling on react-hooks-apollo, and went that route instead. I found it made the code much cleaner.

Just putting it here in case someone else has a similar question (and the total is still hard-coded!).

import React, { useState } from 'react';
import { Grid, GridColumn } from '@progress/kendo-react-grid';
import { LOGS_QUERY } from '../../queries/queries';
import { useQuery } from 'react-apollo-hooks';
import Spinner from '../shared/spinner/Spinner';
import DateCell from '../shared/data-cell/DateCell';
import MessageCell from '../shared/message-cell/MessageCell';
 
 
/**
 * Logging Component
 * - displays logs using Kendo Grid and Apollo Query
 */
const Logging = () => {
 
    /**
     * Default grid state
     */
    const [dataState, setDataState,] = useState({ skip: 0, take: 10 });
 
    /**
     * Default query variables
     */
    const variables = { skip: 0, first: 10, };
 
    /**
     * Logs Query hook
     */
    const { data, error, loading, fetchMore, } = useQuery(LOGS_QUERY, { variables });
 
 
 
    /**
      * Grid dataStateChange Event handler
      *
      * @param {Event} e - dataStateChange Event
      * @return {Promise} - curried function fetchMore Promise
     */
    const dataStateChange = (e) => {
        const { filter, skip, sort, take } = e.data;
 
        setDataState({ filter, skip, sort, take });
 
        return fetchMore({
            variables: {
                skip,
                orderBy: sort
                    ? sort.map((item) => `${item.field}_${item.dir.toUpperCase()}`)
                    : []
            },
            updateQuery: (prev, { fetchMoreResult }) => {
                return fetchMoreResult
                    ? Object.assign({}, { logs: [...fetchMoreResult.logs] })
                    : prev;
            }
        });
    };
 
    // query error
    if (error) {
        return (
            <React.Fragment>
                {`<p>Error: ${error}</p>`}
            </React.Fragment>
        );
    };
 
    // render spinner while query runs
    if (loading) {
        return (
            <Spinner />
        );
    };
     
    // render grid
    return (
        <React.Fragment>
            <h2 className="text-primary">Logging</h2>
            <hr />
            <Grid
                style={{ height: "625px" }}
                data={data.logs || []}
                total={30}
                filterable
                pageable
                sortable
                {...dataState}
                onDataStateChange={dataStateChange}
            >
                <GridColumn field="app_id" title="App Id" />
                <GridColumn field="app_name" title="App Name" />
                <GridColumn field="type" title="Message Type" />
                <GridColumn field="message" cell={MessageCell} title="Message" />
                <GridColumn field="created_on" cell={DateCell} title="Created" />
                <GridColumn field="updated_on" cell={DateCell} title="Updated" />
            </Grid>
        </React.Fragment>
    )
};
 
export { Logging as default };

 

 

 

0
Stefan
Telerik team
answered on 25 Jun 2019, 01:54 PM
Hello, Robert,

Thank you for sharing the code with the community.

We always appreciate sharing examples that can be helpful.

I have added some Telerik points to your account for sharing it.

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
Tags
General Discussions
Asked by
Robert
Top achievements
Rank 1
Answers by
Robert
Top achievements
Rank 1
Stefan
Telerik team
Share this question
or