Giter Site home page Giter Site logo

djanoskova / vuex-but-for-react Goto Github PK

View Code? Open in Web Editor NEW
104.0 3.0 6.0 606 KB

A state management library for React, heavily inspired by vuex

Home Page: https://vuex-but-for-react.netlify.app/

HTML 9.61% TypeScript 90.39%
state flux react state-management

vuex-but-for-react's Introduction

Vuex - But for React! โš›

Enjoy the vuex API in your React applications with vuex-but-for-react, which uses only React Context and React use-sync-external-store 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 โœจ


๐Ÿšจ React versions

vuex-but-for-react >= 3.0.0 works with React 18.0.0+

To use with older react versions, please install vuex-but-for-react 2.0.6

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 (
    ...
  )
}

vuex-but-for-react's People

Contributors

djanoskova avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

vuex-but-for-react's Issues

Can this be used with react-native?

Hi! This is an awesome package! I would love to use this in my react-native app, but I am not sure if it's supported or how can I change it to use it with react-native projects. Any help is highly appreciated.

could you please update react dependency?

plugin depends peer react@"^16.8.0"
but current react version is now @"17.0.2"
could you please fix this!

Thanks in advance!
Very nice Project and I hope I can use it in my Project once updated.

Pass a full VueX Store Object instead of config?

Hi Dana - Thanks for the package, the API looks great and easy to use!

I'm hoping to introduce this on my project, but long story short, I've got a VueX Store that I need to plug into React Native AND I'm also using Vue Native.

The Vue Native part can access the VueX Store as normal, has two-way binding, and is completely reactive.

My issue is, when using withStore(App, config); and instantiating my own Vuex.Store(config); I have two stores! I need to do Vuex.Store() for the Vue part of the application, and the goal is to phase out Vue completely.

I need to pass withStore the actual Vuex.Store or find another solution to this problem, and was wondering if you have any suggestions??

Thanks!

Idea: Pass state to actions context

Another idea that would be useful to me is to access the state inside an action context.

Example:

// store.js
const store = {
  state: { count: 0 },
  mutations: {
    SET_COUNT(state, value) {
      state.count = value;
    }
  },
  actions: {
    increment(context) { // context only contains actions and mutations
      context.mutations.SET_COUNT(context.state.count + 1);
    }
  }
}

Idk if it's possible though, as you mentioned the way the state is written is not really reactive.

Idea: Access state without the need of useGetters

First, thanks for the great package :)

What about a hook to access the state directly instead of having to write a specific getter, such as mapState in VueX?
I find it a bit redundant to write getters for each property of my state.

Example:

// store.js
const store = {
  state: { count: 0 },
  mutations: {
    SET_COUNT(state, value) {
      state.count = value;
    }
  },
  actions: {
    increment(context) {
      context.mutations.SET_COUNT(context.state.count + 1);
    }
  }
}
import { useStoreState } from 'vuex-but-for-react';

export function Counter() {
  const count = useStoreState('count');
  // or const count = useStoreState(state => state.count);

  return //...
}

Module Support?

It would be great to fully support VueX with modules

e.g.

const user = useGetter('user/user');

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.