I am setting up react-admin as a dashboard for a burger restaurant. Here is my My github repository.
I would like to apologize if any required troubleshooting information is missing. I am a bit out of my depth but I am having a go.
I have created two tables (three if you count contacts) to store the menu and the menu categories. I have tried to setup referential integrity. Immediately after doing this (and rebuilding the project with the new seed.sql file) I started getting the following after clicking on "menucategories" on the left-hand side:
Error: The dataProvider threw an error. It should return a rejected Promise instead.
in List (at MenuCategory.js:5)
in CatData (created by WithPermissions)
in WithPermissions (created by Context.Consumer)
in Route (created by ResourceRoutes)
in Switch (created by ResourceRoutes)
in ResourceRoutes (created by Resource)
in Resource (at App.js:41)
in Route (created by RoutesWithLayout)
in Switch (created by RoutesWithLayout)
in RoutesWithLayout (created by Context.Consumer)
in div (created by Layout)
in main (created by Layout)
in div (created by Layout)
in div (created by Layout)
in Layout (created by WithStyles(Layout))
in WithStyles(Layout) (created by Context.Consumer)
in withRouter(WithStyles(Layout)) (created by ConnectFunction)
in ConnectFunction (created by LayoutWithTheme)
in ThemeProvider (created by LayoutWithTheme)
in LayoutWithTheme (created by Context.Consumer)
in Route (created by CoreAdminRouter)
in Switch (created by CoreAdminRouter)
in div (created by CoreAdminRouter)
in CoreAdminRouter (created by Context.Consumer)
in Route (created by CoreAdminUI)
in Switch (created by CoreAdminUI)
in CoreAdminUI (created by AdminUI)
in AdminUI (created by Admin)
in Router (created by ConnectedRouter)
in ConnectedRouter (created by Context.Consumer)
in ConnectedRouterWithContext (created by ConnectFunction)
in ConnectFunction (created by CoreAdminContext)
in TranslationProvider (created by CoreAdminContext)
in Provider (created by CoreAdminContext)
in CoreAdminContext (created by AdminContext)
in AdminContext (created by Admin)
in Admin (at App.js:25)
in ReactAdminWrapper (at App.js:65)
in ApolloProvider (at App.js:64)
in App (at src/index.js:7)
The first lot of error information in the console is like this:
index.js:1 Warning: Failed prop type: The prop `children` is marked as required in `ForwardRef(Link)`, but its value is `null`.
in ForwardRef(Link) (created by WithStyles(ForwardRef(Link)))
in WithStyles(ForwardRef(Link))
in Unknown
in Unknown (at Contacts.js:13)
in td (created by ForwardRef(TableCell))
in ForwardRef(TableCell) (created by WithStyles(ForwardRef(TableCell)))
in WithStyles(ForwardRef(TableCell)) (created by DatagridCell)
in DatagridCell (created by DatagridRow)
in tr (created by ForwardRef(TableRow))
in ForwardRef(TableRow) (created by WithStyles(ForwardRef(TableRow)))
in WithStyles(ForwardRef(TableRow)) (created by DatagridRow)
in DatagridRow
in tbody (created by ForwardRef(TableBody))
in ForwardRef(TableBody) (created by WithStyles(ForwardRef(TableBody)))
in WithStyles(ForwardRef(TableBody)) (created by DatagridBody)
in DatagridBody (created by Datagrid)
in table (created by ForwardRef(Table))
in ForwardRef(Table) (created by WithStyles(ForwardRef(Table)))
in WithStyles(ForwardRef(Table)) (created by Datagrid)
in Datagrid (at Contacts.js:6)
in div (created by ForwardRef(Paper))
in ForwardRef(Paper) (created by WithStyles(ForwardRef(Paper)))
in WithStyles(ForwardRef(Paper)) (created by ForwardRef(Card))
in ForwardRef(Card) (created by WithStyles(ForwardRef(Card)))
in WithStyles(ForwardRef(Card)) (created by ListView)
in div (created by ListView)
in div (created by ListView)
in ListView (created by List)
in List (at Contacts.js:5)
in ContactList (created by WithPermissions)
in WithPermissions (created by Context.Consumer)
in Route (created by ResourceRoutes)
in Switch (created by ResourceRoutes)
in ResourceRoutes (created by Resource)
in Resource (at App.js:26)
in Route (created by RoutesWithLayout)
in Switch (created by RoutesWithLayout)
in RoutesWithLayout (created by Context.Consumer)
in div (created by Layout)
in main (created by Layout)
in div (created by Layout)
in div (created by Layout)
in Layout (created by WithStyles(Layout))
in WithStyles(Layout) (created by Context.Consumer)
in withRouter(WithStyles(Layout)) (created by ConnectFunction)
in ConnectFunction (created by LayoutWithTheme)
in ThemeProvider (created by LayoutWithTheme)
in LayoutWithTheme (created by Context.Consumer)
in Route (created by CoreAdminRouter)
in Switch (created by CoreAdminRouter)
in div (created by CoreAdminRouter)
in CoreAdminRouter (created by Context.Consumer)
in Route (created by CoreAdminUI)
in Switch (created by CoreAdminUI)
in CoreAdminUI (created by AdminUI)
in AdminUI (created by Admin)
in Router (created by ConnectedRouter)
in ConnectedRouter (created by Context.Consumer)
in ConnectedRouterWithContext (created by ConnectFunction)
in ConnectFunction (created by CoreAdminContext)
in TranslationProvider (created by CoreAdminContext)
in Provider (created by CoreAdminContext)
in CoreAdminContext (created by AdminContext)
in AdminContext (created by Admin)
in Admin (at App.js:25)
in ReactAdminWrapper (at App.js:65)
in ApolloProvider (at App.js:64)
in App (at src/index.js:7)
I was referring to the following tutorial when learning how to setup the referential integrity.
Please note the seed.sql file has has not been updated in the repo to the version I am working on (on my machine) which is as follows:
CREATE EXTENSION IF NOT EXISTS "uuid-ossp" WITH SCHEMA public;
DROP TABLE IF EXISTS public.contacts CASCADE;
CREATE TABLE public.contacts (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4() NOT NULL,
email VARCHAR(255) NOT NULL,
firstname VARCHAR(255),
lastname VARCHAR(255),
website VARCHAR(255),
streetaddress VARCHAR(255),
phone VARCHAR(255),
companyname VARCHAR(255),
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX contacts_email_index ON public.contacts (email);
DROP TABLE IF EXISTS public.menu CASCADE;
CREATE TABLE public.menu (
id SERIAL PRIMARY KEY,
title VARCHAR(255) NOT NULL,
category_id INT NOT NULL CONSTRAINT menu__ref_p REFERENCES menucategories,
price NUMERIC(8, 2),
desc1 VARCHAR(255),
isenabled BOOLEAN NOT NULL DEFAULT TRUE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
DROP TABLE IF EXISTS public.menucategories CASCADE;
CREATE TABLE public.menucategories (
category_id SERIAL PRIMARY KEY,
catname VARCHAR(255) NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
SET client_min_messages = INFO;
Test data is prefilled into the database through the fixtures.sql file
INSERT INTO public.contacts
(
id,
email,
firstname,
lastname
)
SELECT
('1de9c987-08ab-32fe-e218-89c124cd' || to_char(seqnum, 'FM0000'))::uuid,
'firstname' || to_char(seqnum, 'FM0000') || '@example.com',
'firstname' || to_char(seqnum, 'FM0000'),
'lastname' || to_char(seqnum, 'FM0000')
FROM
GENERATE_SERIES(1, 2) seqnum;
TRUNCATE public.menu CASCADE;
INSERT INTO public.menucategories
(
catname
)
SELECT
('category' || to_char(seqnum, 'FM0000'))
FROM
GENERATE_SERIES(1, 3) seqnum;
Here is the code in my App.js file:
import React, { useEffect, useState } from 'react'
import { ApolloProvider } from '@apollo/react-hooks';
import { Admin, Resource } from 'react-admin'
import { useApolloClient } from '@apollo/react-hooks'
import pgDataProvider from 'ra-postgraphile'
import { ContactList, ContactEdit, ContactCreate } from './Contacts'
import { MenuData, MenuEdit, CreateMenuItem } from './Menu'
import { CatData, CatEdit, CreateCatItem } from './MenuCategory'
import ApolloClient from './Apollo';
/* import { HttpError } from 'react-admin'; */
const ReactAdminWrapper = () => {
const [dataProvider, setDataProvider] = useState(null);
const client = useApolloClient();
useEffect(() => {
(async () => {
const dataProvider = await pgDataProvider(client);
setDataProvider(() => dataProvider);
})()
}, [client]);
return (
dataProvider && (
<Admin dataProvider={dataProvider}>
<Resource
name="contacts"
list={ContactList}
edit={ContactEdit}
create={ContactCreate}
/>
<Resource
name="menu"
list={MenuData}
edit={MenuEdit}
create={CreateMenuItem}
/>
<Resource
name="menucategories"
list={CatData}
edit={CatEdit}
create={CreateCatItem}
/>
</Admin>
)
);
}
const App = () => {
return (
<ApolloProvider client={ApolloClient}>
<ReactAdminWrapper />
</ApolloProvider>
);
}
export default App;
I am using AutocompleteInput to (hard-code) prefill the values but I need to change that to something like ReferenceField or ReferenceInput to pull the categories from the database. I am just not 100% sure on how to do this as I am new to react-admin. Any suggestions would be much appreciated.
My Menu.js file is as follows:
import React from 'react';
import { List, Datagrid, Edit, Create, SimpleForm, TextField, EditButton, TextInput, BooleanInput, BooleanField } from 'react-admin';
import { AutocompleteInput } from 'react-admin';
export const MenuData = (props) => (
<List {...props}>
<Datagrid>
<TextField source="title" />
<TextField source="category_id" />
<TextField source="price" />
<TextField source="desc1" />
{/* <TextField source="image" /> */}
<BooleanField label="enabled" source="isenabled" />
<EditButton basePath="/menu" />
</Datagrid>
</List>
);
const MenuTitle = ({ record }) => {
return <span>Menu {record ? `"${record.title}"` : ''}</span>;
};
export const MenuEdit = (props) => (
<Edit title={<MenuTitle />} {...props}>
<SimpleForm>
<TextInput disabled source="id" />
<TextInput source="title" />
{/* //These are currently hardcoded see: https://marmelab.com/react-admin/Inputs.html
//We want to grab the values from the database instead */}
<AutocompleteInput source="category_id" choices={[
{ id: '1', name: 'category0001' },
{ id: '2', name: 'category0002' },
{ id: '3', name: 'category0003' },
]} />
{/* <TextInput source="category_id" /> */}
<TextInput source="price" />
<TextInput disabledsource="image" />
<TextInput source="desc1" />
<BooleanInput label="Enabled" source="isenabled" />
</SimpleForm>
</Edit>
);
export const CreateMenuItem = (props) => (
<Create title="Add a Menu Item" {...props}>
<SimpleForm>
<TextInput disabled source="id" />
<TextInput source="title" />
<AutocompleteInput source="category_id" choices={[
{ id: '1', name: 'category0001' },
{ id: '2', name: 'category0002' },
{ id: '3', name: 'category0003' },
]} />
{/* <TextInput source="category_id" /> */}
<TextInput source="price" />
{/* <TextInput disabledsource="image" /> */}
<TextInput source="desc1" />
</SimpleForm>
</Create>
);
import React from 'react';
import { List, Datagrid, Edit, Create, SimpleForm, TextField, EditButton, TextInput } from 'react-admin';
//ReferenceField
export const CatData = (props) => (
<List {...props}>
<Datagrid>
<TextField source="catname" />
<EditButton basePath="/menucategories" />
</Datagrid>
</List>
);
const CatTitle = ({ record }) => {
return <span>Category {record ? `"${record.title}"` : ''}</span>;
};
export const CatEdit = (props) => (
<Edit title={<CatTitle />} {...props}>
<SimpleForm>
<TextInput disabled source="id" />
<TextInput label="Category name" source="catname" />
</SimpleForm>
</Edit>
);
export const CreateCatItem = (props) => (
<Create title="Add a Category" {...props}>
<SimpleForm>
<TextInput disabled source="id" />
<TextInput label="Category name" source="catname" />
</SimpleForm>
</Create>
);
Any help or assistance would be greatly appreciated.