Skip to content

Genrate/genrate-react-redux

Repository files navigation

GenRate React Redux

npm package Build Status Downloads Issues codecov Commitizen Friendly Semantic Release

GenRate React Redux package is combination of Genrate React and Redux approach

Advantages

  • Separate Logic & Design
  • Preserve UI Design
  • Components Flexible Reusability
  • Simplify re-render handling
  • Encourage micro components

Installation

npm install @genrate/react-redux

Usage

Component

import { useData } from '@genrate/react-redux';
import PostAPI from '@api/posts';
import User from '@models/user';

// Output
const Avatar = ({ fullname }) => (
  <h5>{fullname}</h5>
);

const Post = ({ content = 'My first post' }) => (
  <li>
    {content}
  </li>
);

const PostFallback = ({ title = 'Loading ...' }) => (
  <p>{title}</p>
);

// Input
const AddPost = () => (
  <div>
    <input name="newPost" />
    <button>Add Post</button>
  </div>
);

// Layout
const Header = () => (
  <div>
    <Avatar />
    <button>Logout</button>
  </div>
);

const Footer = () => (<div>© 2024</div>);

const PostsLayout = () => (
  <div>
    <Header />
    <AddPost />
    <ul>
      <Post />
    </ul>
    <Footer />
  </div>
);

// Functionality 
const PostLists = () => {
  
  const { view, each, query, model, pass, attach } = useData({

    // local state
    local: {
      newPost: ''
    },

    // redux selectors
    selectors: {

      // manual selector 
      userId: () => (state) => state.user.id

      // using @generate/redux
      fullname: () => User.fullname,
    },

    // react hooks
    hooks: {

      // rtx query application
      posts: ({ userId }) => PostAPI.useGetByUserQuery(userId),

      // set specific data key for hooks that returns array
      'addPost|addStatus': () => PostAPI.useAddPostMutation(),
    },
  });

  // redux actions
  const logout = User.useLogout();

  // render only once

  return view(PostsLayout, {

    // query inside a component
    Header: query({

      // pass data to component as props
      Avatar: pass('fullname'),

      // apply action event
      button: () => () => ({
        onClick: () => logout()
      })
    }),
    
    
    AddPost: query({

      // bind input model default to `name` props
      input: model(),

      button: 
        // subscribe to specific data
        ({ newPost, addPost, addStatus }) => 

        // set props to button component
        () => ({
          onClick: () => addPost({ content: newPost }),
          disabled: addStatus.isLoading
        })
    }),
    
    // iterate component base on posts data
    Post: each(
      ({ posts }) =>
      () => posts?.data?.map(
        // pass content props to each post component
        p => ({ content: p.content })
      ) ?? [
        // attach fallback component when posts is loading or empty
        attach(PostFallback, { 
          title: posts?.isLoading ? 'Loading posts...' : 'No posts found' }
        )
      ]
    ),
  });
};

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published