All Projects → DJanoskova → vuex-but-for-react

DJanoskova / vuex-but-for-react

Licence: other
A state management library for React, heavily inspired by vuex

Programming Languages

typescript
32286 projects
HTML
75241 projects

Projects that are alternatives of or similar to vuex-but-for-react

Reatom
State manager with a focus of all needs
Stars: ✭ 567 (+490.63%)
Mutual labels:  flux, state-management, state
temperjs
State management for React, made simple.
Stars: ✭ 15 (-84.37%)
Mutual labels:  flux, state-management, state
Little State Machine
📠 React custom hook for persist state management
Stars: ✭ 654 (+581.25%)
Mutual labels:  flux, state-management, state
RxReduxK
Micro-framework for Redux implemented in Kotlin
Stars: ✭ 65 (-32.29%)
Mutual labels:  flux, state-management, state
mutable
State containers with dirty checking and more
Stars: ✭ 32 (-66.67%)
Mutual labels:  flux, state-management, state
ReduxSimple
Simple Stupid Redux Store using Reactive Extensions
Stars: ✭ 119 (+23.96%)
Mutual labels:  state-management, state
vue-reactive-store
A VueX alternative : declarative + reactive + centralized way to structure your data store. Inspired by VueX and Vue.js . Compatible with vue-devtools.
Stars: ✭ 27 (-71.87%)
Mutual labels:  state-management, state
xstate
State machines and statecharts for the modern web.
Stars: ✭ 21,286 (+22072.92%)
Mutual labels:  state-management, state
agile
🌌 Global State and Logic Library for JavaScript/Typescript applications
Stars: ✭ 90 (-6.25%)
Mutual labels:  state-management, state
rex-state
Convert hooks into shared states between React components
Stars: ✭ 32 (-66.67%)
Mutual labels:  state-management, state
tstate-machine
TypeScript implementation of State Manager(like StateMachine)
Stars: ✭ 20 (-79.17%)
Mutual labels:  state-management, state
restate
A redux fractal state library 🕷
Stars: ✭ 55 (-42.71%)
Mutual labels:  state-management, state
teaful
🍵 Tiny, easy and powerful React state management
Stars: ✭ 638 (+564.58%)
Mutual labels:  state-management, state
okito
Your best flutter coding friend. All in one; state management, navigation management(with dynamic routing), local storage, localization, dependency injection, cool extensions with best usages and with the support of best utilities!
Stars: ✭ 37 (-61.46%)
Mutual labels:  state-management, state
mafuba
Simple state container for react apps.
Stars: ✭ 20 (-79.17%)
Mutual labels:  flux, state
useSharedState
useSharedState is a simple hook that can be used to share state between multiple React components.
Stars: ✭ 0 (-100%)
Mutual labels:  state-management, state
vue
Vue integration for Nano Stores, a tiny state manager with many atomic tree-shakable stores
Stars: ✭ 25 (-73.96%)
Mutual labels:  state-management, state
react-cool-form
😎 📋 React hooks for forms state and validation, less code more performant.
Stars: ✭ 246 (+156.25%)
Mutual labels:  state-management, state
react-evoke
Straightforward action-driven state management for straightforward apps built with Suspense
Stars: ✭ 15 (-84.37%)
Mutual labels:  flux, state-management
XUI
XUI makes modular, testable architectures for SwiftUI apps a breeze!
Stars: ✭ 100 (+4.17%)
Mutual labels:  state-management, state

Vuex - But for React!

If you know vuex, you know it's as close as we get to a perfect state management library. What if we could do this in the react world?

Enjoy the vuex API in your React applications with vuex-but-for-react, which uses only React itself under the hood. vuex-but-for-react was engineered with developer experience in mind, making it very easy to use. Invoke your getter or action by using a one-line hook and don't worry about unnecessary renders - without using memo.

Your component will render only when its getter changes - and it doesn't care about the rest of the store!

Are you on board? Read more 👇

Installation

npm install vuex-but-for-react --save

yarn add vuex-but-for-react

TS support included

Working example

store.js

const store = {
  state: {
    posts: []
  },
  mutations: {
    POSTS_SET(state, data) {
      state.posts = data
    }
  },
  actions: {
    async POSTS_FETCH(context) {
      const response = await fetch('https://jsonplaceholder.typicode.com/posts')
      const data = await response.json()
      context.mutations.POSTS_SET(data)
    }
  },
  getters: {
    posts (state) {
      return state.posts
    }
  }
}

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { withStore } from 'vuex-but-for-react';

import App from './App';
import store from './store';

const AppWithStore = withStore(App, store);

ReactDOM.render(
  <AppWithStore />,
  document.getElementById('root')
);

Posts.js

import React, { useEffect } from 'react';
import { useAction, useGetter } from 'vuex-but-for-react';

const Posts = () => {
  const handleAction = useAction('POSTS_FETCH');
  const posts = useGetter('posts');

  useEffect(() => {
    handleAction();
  }, [handleAction]) // don't worry, it doesn't re-create!
  
  return (
    <ul>
      {posts.map(post => <li key={post.id}>{post.title}</li>)}
    </ul>
  );
}

export default Posts

Check the examples section to see JavaScript and TypeScript working apps!

API

useAction(actionName)

An action is used for async data logic, especially API calls. You can dispatch mutations and other actions from within an action.

The function returned by the useAction() hook is never re-created.

import { useAction } from 'vuex-but-for-react';

const PostsPage = () => {
  const handleFetch = useAction('POSTS_FETCH');

  useEffect(() => {
    handleFetch();
  }, [handleFetch])

  return (
    ...
  )
}

useMutation(actionName)

A mutation is used for sync data operations. It has access to the current state in order to alter it.

The function returned by the useMutation() hook is never re-created.

import { useMutation } from 'vuex-but-for-react';

const Counter = () => {
  const handleIncrement = useMutation('COUNTER_INCREMENT');
  const handleDecrement = useMutation('COUNTER_DECREMENT');

  return (
    <>
      <button onClick={handleDecrement}>-</button>
      <button onClick={handleIncrement}>+</button>
    </>
  )
}

useGetter(actionName)

A getter gives you the current stored value based on your config. It has access to the current state.

The data returned by the useGetter() hook is updated only in case the shallow value changes. An update of one getter value won't trigger the update of another getter value.

import { useGetter } from 'vuex-but-for-react';

const PostsPage = () => {
  const posts = useGetter('posts');

  return (
    <ul>
      {posts.map(post => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  )
}

withStore(Component, config)

In order to initialize the global store, wrap your (chosen) root component in your store config.

import { withStore } from 'vuex-but-for-react';

const AppWithStore = withStore(App, store);

And more amazing stuff!

useActionOnMount(actionName)

Avoid calling useEffect manually. Just pass the action name and it will be executed on component mount automatically.

import { useActionOnMount, useGetter } from 'vuex-but-for-react';

const PostsPage = () => {
  useActionOnMount('POSTS_FETCH');
  const posts = useGetter('posts');

  return (
    ...
  )
}

What's going on?

This library uses React's Context API under the hood. The withStore() higher order component is creating several contexts:

  • A context provider for actions, wrapped in a memo() to prevent re-creating
  • A context provider for mutations, wrapped in a memo() to prevent re-creating
  • A context provider for a collection of getter contexts, wrapped in a memo() to prevent re-creating
  • Dynamically created context (and provider) for each one of your getters. This allows us using useGetter() inside a component, which always attaches to its own context. It's an alternative solution to a single-state object context. Updating a getter's provider value will not affect other getters' provider value.
  • Under those contexts, there's the provided App component, wrapped in a memo() to prevent re-creating. Even if the parent context providers change value, App won't re-render and neither will its children, unless they're connected to the getter that was changed.

Tree visualization

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].