Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

Sorry, you do not have permission to ask a question, You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please type your username.

Please type your E-Mail.

Please choose an appropriate title for the post.

Please choose the appropriate section so your post can be easily searched.

Please choose suitable Keywords Ex: post, video.

Browse

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Logo Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Logo

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Navigation

  • Home
  • About Us
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • About Us
  • Contact Us
Home/ Questions/Q 8331

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Latest Questions

Author
  • 60k
Author
Asked: November 28, 20242024-11-28T12:07:08+00:00 2024-11-28T12:07:08+00:00

Loadables – a simple way to load data in React

  • 60k

The real-world app involves data loading via some API and showing UI based on the states of the API. For example, while data is loading, you may show a loader animation, but on error, you may show an error UI. This fairly simple-looking task ends up getting complex super fast and is more difficult to maintain with all the spaghetti code for UI synchronization. So here I propose the loadable pattern to simplify data loading and synchronize the UI with it.

In this example, we are going to load a list of todos. Here we are using react-redux as a state management solution. Below we will see how to create a store and reducer with react-redux. However, you can directly skip to “loadables” if you familiar with react-redux-context store.

Create react-redux context store

Let's start by creating a react-redux-context-store for storing our todos. The following sample is taken from react-redux.

// [filename: todo.store.jsx]  import React from 'react' import {   Provider,   createStoreHook,   createDispatchHook,   createSelectorHook,  from "react-redux"; import { createStore } from "redux"; // reducer for the state import { reducer } from "./store.reducer"  // react context store const TodoContext = React.createContext(null)  // create redux state selector and dispatch from context export const useTodoStore = createStoreHook(TodoContext) export const useTodoDispatch = createDispatchHook(TodoContext) export const useTodoSelector = createSelectorHook(TodoContext)  // create redux store from the reducer const todoStore = createStore(reducer)  // create store provider wrap subtree export function TodoStoreProvider({ children }) {   return (     <Provider context={TodoContext} store={todoStore}>       {children}     </Provider>   ) } 
Enter fullscreen mode Exit fullscreen mode

After creating a store provider we are going to create store.reducer.js where we define the reducer and actions for the store.

// [filename: todo.reducer.js]  export const loadNext = () => ({ type: 'load_next' }); export const addTodos = ({ todos, total }) => ({ type: 'add_todos', payload: { todos, total } }); export const setLoading = (loading) => ({ type: 'set_loading', payload: { loading }  });  const InitState = {  status: 'idle', // idle | pending | resolve | reject   todos: [],  total: 0,  skip: 0,  limit: 10 };  export const reducer = (state = InitState, action) => {   switch (action.type) {     case 'load_next': {        if (state.todos.length < state.total && state.status !== 'pending') {           return {              ...state,              status:  'pending'           };        }        return state;     }     case 'add_todos': {       return {           ...state,           status: 'resolve',           todos: [...state.todos, ...action.payload.todos],           total: state.total + action.payload.todos.length        };     }     case 'set_loading': {       return {           ...state,           status: action.payload.loading       };     }     default: {       return state;     }   } }; 
Enter fullscreen mode Exit fullscreen mode

Loadable

Loadables are react components that wrap all data loading logic in it and update the store.

// [filename: App.js]  const App = () => (   <div>     <TodoStoreProvider>       {/* Loadable holds all data loading logic*/}       <TodoLoadable>         {/* Render todos */}       </TodoLoadable>      </TodoStoreProvider>    </div>  ); 
Enter fullscreen mode Exit fullscreen mode

Now let's create a loadable:

// [filename: Todo.loadable.js]  function TodoLoadable(props) {   // react-redux state slice selector   const skip = useTodoSelector((state) => state.skip);   const limit = useTodoSelector((state) => state.limit);   const todoDispatch = useTodoDispatch();   // load data   useEffect(() => {     todoDispatch(setLoading('pending'));     api({ skip, limit })       .then((res) => todoDispatch({ todos: res.todos, total: res.total }))       .catch((e) => todoDispatch(setLoading('reject')));   }, [skip, limit]);   // render child   return <>{props.children}</> } 
Enter fullscreen mode Exit fullscreen mode

The point to note here is that the loading logic is completely placed inside the loadable and the children can utilize the store to sync UI state accordingly. IsVisible is a utility component that can be used to render things conditionally.

// [filename: IsVisible.utility.jsx]  function IsVisible({ visible, unmountOnExit, ...props }) {      if (unmountOnExit && !visible) {     return null;   }   return <div {...props} style={{  ...props.style, display: visible ? 'flex' : 'none'  }} /> } 
Enter fullscreen mode Exit fullscreen mode

We can use the IsVisible utility component to create state synced UI.

// [filename: Todo.jsx]  const Error = () => <div><h1>Error</h1></div>; const Loader = () => <CircularProgress size="small" /> const Todos = () => {   const todos = useTodoSelector((state) => state.todos);   return <div>{todos.map((todo) => <h1>{todo}</h1>)}</div> }  function IsErrorVisible(props) {   const isError = useTodoSelector((state) => state.status === 'reject');   return <IsVisible {...props} visible={isError} /> }  ....more IsVisible for all API status 'reject' | 'resolve' | 'pending' | 'idle' 
Enter fullscreen mode Exit fullscreen mode

Now with the help of this IsVisible, we can render UI according to the state of API.

// [filename: App.js]  const App = () => (   <div>     <TodoStoreProvider>       {/* Loadable holds all data loading logic*/}       <TodoLoadable>         <IsErrorVisible><ErrorUI /></IsErrorVisible>         <IsTodoVisible><Todos /></IsTodoVisible>         <IsLoaderVisible><Loader /></IsLoaderVisible>       </TodoLoadable>      </TodoStoreProvider>    </div>  ); 
Enter fullscreen mode Exit fullscreen mode

This is how loadable along with IsVisible utility makes it super easy to load data in react and make a code simple to write and understand. Here is a link to demo Codesandbox.

javascriptreacttutorialwebdev
  • 0 0 Answers
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

Sidebar

Ask A Question

Stats

  • Questions 4k
  • Answers 0
  • Best Answers 0
  • Users 1k
  • Popular
  • Answers
  • Author

    How to ensure that all the routes on my Symfony ...

    • 0 Answers
  • Author

    Insights into Forms in Flask

    • 0 Answers
  • Author

    Kick Start Your Next Project With Holo Theme

    • 0 Answers

Top Members

Samantha Carter

Samantha Carter

  • 0 Questions
  • 20 Points
Begginer
Ella Lewis

Ella Lewis

  • 0 Questions
  • 20 Points
Begginer
Isaac Anderson

Isaac Anderson

  • 0 Questions
  • 20 Points
Begginer

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help

Footer

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise

Querify Question Shop: Explore, ask, and connect. Join our vibrant Q&A community today!

About Us

  • About Us
  • Contact Us
  • All Users

Legal Stuff

  • Terms of Use
  • Privacy Policy
  • Cookie Policy

Help

  • Knowledge Base
  • Support

Follow

© 2022 Querify Question. All Rights Reserved

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.