Development of a client's personal account on React

 A large number of web applications today require dynamic web pages where users access and interact with content. Interaction with content often happens via API, i.e. operations are performed by sending special requests to the backend server. In such situations, it often becomes necessary to have a personal account where the user can perform some actions, and the administrator and moderators can track changes and, if necessary, make changes.

A common practice when creating an interface is to connect each endpoint to a specific API request. Using the react-admin framework, this process has become much easier and faster. React-admin is a framework that was created specifically for developing admin interfaces by interacting with APIs - via Rest, GraphQL, or custom schemas. You don't have to worry about style formatting as the framework is based on Material UI, the React library used to develop application interfaces.Probably, in the development of Mosoblayirts, the client's personal account used various technologies that make it convenient for users.

Installing React and React-Admin

First, let's create a new React project and install react-admin. To do this, run the following commands:

npx create-react-app react-admin-demo-app
cd react-admin-demo-app/
npm i react-admin ra-data-json-server prop-types
npm start

Your empty React app should now be up and running on port 3000.

API as a data source

It is essential for our admin panel to have CRUD functionality. To do this, we will use the API to show how the application reacts to our actions. Let's use JSONPlaceholder, a dummy REST API that exists for demo purposes.

Sample output when accessing this API:

curl https://jsonplaceholder.typicode.com/users/4
{
  "id": 4,
  "name": "Patricia Lebsack",
  "username": "Karianne",
  "email": "Julianne.OConner@kory.org",
  "address": {
    "street": "Hoeger Mall",
    "suite": "Apt. 692",
    "city": "South Elvis",
    "zipcode": "53919-4257",
    "geo": {
      "lat": "29.4572",
      "lng": "-164.2990"
    }
  },
  "phone": "493-170-9623 x156",
  "website": "kale.biz",
  "company": {
    "name": "Robel-Corkery",
    "catchPhrase": "Multi-tiered zero tolerance productivity",
    "bs": "transition cutting-edge web services"
  }
}

Let's try to fetch data from the API. For this purpose, react-admin uses <Admin>, the root component, to enable communication between APIs and applications. Let's change the default code in src/App.js as follows:

//src/app.js
import React from 'react';
import { Admin } from 'react-admin';
import jsonServerProvider from 'ra-data-json-server';

const dataProvider = jsonServerProvider('https://jsonplaceholder.typicode.com');
const App = () => <Admin dataProvider = {dataProvider} />;

export default App;

After such a change in the browser window, we should see the following screen:

During development, react-admin creates interfaces using the “guessers” component. When data is received, ListGuesserit analyzes the best way to display the data. Let's add it to the code <ListGuesser>and look at the result:

//src/App.js shows only changed dates
import { Admin, Resource, ListGuesser } from 'react-admin';
...
const App = () => (
  <Admin dataProvider = {dataProvider}>
    <Resource name='users' list={ListGuesser} />
  </Admin>
);
...

The parameter list = {ListGuesser}means that react adminthe component should use <ListGuesser>to display a list of messages. 

The line <Resource name="users" />says react-adminto get "users" from the API URL. <Resource>also defines the React components to be used for each CRUD operation. If you now open it Web Developer Toolsin a browser, you can see what /userswas automatically added to the dataProviderURL, after which the result was obtained.

It is worth remembering that the component <ListGuesser>is not intended for use in production, so it must be replaced with a custom component. An amazing feature of gessers is to display the source code of the data received from the API in the browser console.

This allows us to understand what our list of users should look like. Let's implement a custom component in our application, using the code provided by Gesser as a basis. srcCreate a file in the project folder users.js:

import React from 'react';
import { List, Datagrid, TextField, EmailField, UrlField } from 'react-admin';
export const UserList = props => (
  <List {...props}>
    <Datagrid rowClick='edit'>
      <TextField source='id' />
      <TextField source='name' />
      <TextField source='username' />
      <EmailField source='email' />
      <TextField source='address.street' label='Address' />
      <TextField source='phone' />
      <UrlField source='website' />
      <TextField source='company.name' label='Company' />
    </Datagrid>
  </List>
);

There are a few changes in the code block above. <UrlField>we use to make links in a column of our site clickable. We then add a property labelto the address and company columns to make their headings more presentable. Let's go to App.jsand replace ListGuesserwith UserList.

//src/App.js shows only changed dates
...
import { Admin, Resource } from 'react-admin';
import { UserList } from './users';
...
const App = () => (
  <Admin dataProvider = {dataProvider}>
    <Resource name='users' list={UserList} />
  </Admin>
);
...

There will be minimal changes in the browser, except for the field with the site address, which became clickable thanks to UrlFieldNow we have created our own component, which we can customize according to the needs of the application.

How does it all work?

The main user list component is the component responsible for getting information from the API, displaying the page title, and handling pagination. This list then delegates the display of the actual list of users to its child element. In this case, it's a component that renders a table with one row for each entry. <Datagrid>uses its child components ( <TextField><EmailField>and others) to define the columns to render. Each component <Field>renders a separate field in the API response, specified by the source.

ListGuessercreated one column for each field in the response. Often this is too much to visualize, so you can remove less important fields or those that are not needed at all. The process just implemented reflects the initial stage of development using react-admin. First of all, the “fortune teller” will do the work and issue a list, then we will select the fields necessary to display and present them in a custom component for further customization.

Creating and editing data

Any administrative panel should allow the user to create and edit data. React Admin also makes it easy to organize this process using the EditGuesserTo do this, we import it in our App.js file and add it to the <Resourse>.

//src/App.js shows only modified lines
import { Admin, Resource, EditGuesser } from "react-admin";
...
<Resource name='users' list={UserList} edit={EditGuesser} />
...

We can now edit user details in our admin interface.we're using has no editing or creation functionality. This is where a concept called optimistic rendering comes into play - which react admin uses to display changes made while sending an update request in the background at the same time. If the request fails, the data is returned to its original form.

Similar to a lesser with a list of users, you can find code in the browser console to render the information displayed in the editor.


Let's transfer the proposed structure to our users.js by making a few adjustments to the fields.

export const UserEdit = props => (
  <Edit {...props}>
    <SimpleForm>
      <TextInput disabled source='id' />
      <TextInput source='name' />
      <TextInput source='username' />
      <TextInput source='email' />
      <TextInput source='address.street' label='Address' />
      <TextInput source='phone' />
      <UrlField source='website' />
      <TextInput source='company.name' label='Company' />
    </SimpleForm>
  </Edit>
);

Adding disableda-c to the field idwill prevent it from being edited, since this is a sensitive data field and can be linked to the user. In order to avoid violation of the database structure, such fields must be disabled for editing.

In  we App.jsreplace  EditGuesser with the newly created component  UserEdit:

...
import  { UserList, UserEdit }  from './users';
...
<Resource name='users' list={UserList} edit={UserEdit} />
...

The process of creating a new user is similar to editing a single record. To implement user creation, add the following code to users.js:

...
import { Create, List, Datagrid, TextField, EmailField, Edit, UrlField, SimpleForm, TextInput } from 'react-admin';
...
export const UserCreate = props => (
  <Create {...props}>
    <SimpleForm>
      <TextInput source='name' />
      <TextInput source='username' />
      <TextInput source='email' />
      <TextInput source='address.street' label='Address' />
      <TextInput source='phone' />
      <UrlField source='website' />
      <TextInput source='company.name' label='Company' />
    </SimpleForm>
  </Create>
);

App.js add component  UserCreate:

...
<Resource name='users' list={UserList} edit={UserEdit} create={UserCreate} />
...

Now we can create a new user. Similar to the editing process, user creation is done using optimistic rendering. The request to the server is executed after being displayed in the browser, after which we will receive an error that the entry was not found, because. our demo API does not support POST/PUT operations.

Comments