• Stars
    star
    2,559
  • Rank 17,924 (Top 0.4 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 7 years ago
  • Updated almost 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Simple React state management. Made with ❤️ and ES6 Proxies.

React Easy State - by RisingStack

Build dependencies Status Coverage Status Package size Version License All Contributors

Browser support

NEWS: v6.3.0 fixed a nasty bug that could render zombie children. Please update to this version at least to save yourself some headaches. Thanks!

Table of Contents

Introduction 👋

React Easy State is a practical state management library with two functions and two accompanying rules.

  1. Always wrap your components with view().
  2. Always wrap your state store objects with store().
import React from 'react';
import { store, view } from '@risingstack/react-easy-state';

const counter = store({
  num: 0,
  increment: () => counter.num++
});

export default view(() => (
  <button onClick={counter.increment}>{counter.num}</button>
));

This is enough for it to automatically update your views when needed. It doesn't matter how you structure or mutate your state stores, any syntactically valid code works.

Check this TodoMVC codesandbox or raw code for a more exciting example with nested data, arrays and getter properties.

Installation 💿

npm install @risingstack/react-easy-state

Setting up a quick project

Easy State supports Create React App without additional configuration. Just run the following commands to get started.

npx create-react-app my-app
cd my-app
npm install @risingstack/react-easy-state
npm start

You need npm 5.2+ to use npx.

Everyday Usage 😎

Creating global stores

store creates a state store from the passed object and returns it. A state store behaves just like the passed object. (To be precise, it is a transparent reactive proxy of the original object.)

import { store } from '@risingstack/react-easy-state';

const user = store({ name: 'Rick' });
// stores behave like normal JS objects
user.name = 'Bob';
State stores may have arbitrary structure and they may be mutated in any syntactically valid way.

import { store } from '@risingstack/react-easy-state';

// stores can include any valid JS structure
// including nested data, arrays, Maps, Sets, getters, setters, inheritance, ...
const user = store({
  profile: {
    firstName: 'Bob',
    lastName: 'Smith',
    get name() {
      return `${user.profile.firstName} ${user.profile.lastName}`;
    },
  },
  hobbies: ['programming', 'sports'],
  friends: new Map(),
});

// stores may be mutated in any syntactically valid way
user.profile.firstName = 'Bob';
delete user.profile.lastName;
user.hobbies.push('reading');
user.friends.set('id', otherUser);

Async operations can be expressed with the standard async/await syntax.

import { store } from '@risingstack/react-easy-state';

const userStore = store({
  user: {},
  async fetchUser() {
    userStore.user = await fetch('/user');
  },
});

export default userStore;

State stores may import and use other state stores in their methods.

userStore.js

import { store } from '@risingstack/react-easy-state';

const userStore = store({
  user: {},
  async fetchUser() {
    userStore.user = await fetch('/user');
  },
});

export default userStore;

recipesStore.js

import { store } from '@risingstack/react-easy-state';
import userStore from './userStore';

const recipesStore = store({
  recipes: [],
  async fetchRecipes() {
    recipesStore.recipes = await fetch(
      `/recipes?user=${userStore.user.id}`,
    );
  },
});

export default recipesStore;

Wrap your state stores with store as early as possible.

// DON'T DO THIS
const person = { name: 'Bob' };
person.name = 'Ann';

export default store(person);
// DO THIS INSTEAD
const person = store({ name: 'Bob' });
person.name = 'Ann';

export default person;

The first example wouldn't trigger re-renders on the person.name = 'Ann' mutation, because it is targeted at the raw object. Mutating the raw - none store-wrapped object - won't schedule renders.

Avoid using the this keyword in the methods of your state stores.

import { store, view } from '@risingstack/react-easy-state';

const counter = store({
  num: 0,
  increment() {
    // DON'T DO THIS
    this.num++;
    // DO THIS INSTEAD
    counter.num++;
  },
});

export default view(() => (
  <div onClick={counter.increment}>{counter.num}</div>
));

this.num++ won't work, because increment is passed as a callback and loses its this. You should use the direct object reference - counter - instead of this.

Creating reactive views

Wrapping your components with view turns them into reactive views. A reactive view re-renders whenever a piece of store - used inside its render - changes.

import React from 'react';
import { view, store } from '@risingstack/react-easy-state';

// this is a global state store
const user = store({ name: 'Bob' });

// this is re-rendered whenever user.name changes
export default view(() => (
  <div>
    <input
      value={user.name}
      onChange={ev => (user.name = ev.target.value)}
    />
    <div>Hello {user.name}!</div>
  </div>
));
Wrap ALL of your components with view - including class and function ones - even if they don't seem to directly use a store.

Every component that is using a store or part of a store inside its render must be wrapped with view. Sometimes store usage is not so explicit and easy to to miss.

import { view, store } from '@risingstack/react-easy-state';

const appStore = store({
  user: { name: 'Ann' },
});

const App = view(() => (
  <div>
    <h1>My App</h1>
    <Profile user={appStore.user} />
  </div>
));

// DO THIS
const Profile = view(({ user }) => <p>Name: {user.name}</p>);

// DON'T DO THIS
// This won't re-render on appStore.user.name = 'newName' like mutations
const Profile = ({ user }) => <p>Name: {user.name}</p>;

If you are 100% sure that your component is not using any stores you can skip the view wrapper.

import React from 'react';

// you don't have to wrap this component with `view`
export default (() => <p>This is just plain text</p>);

view wrapping is advised even in these cases though.

  • It saves you from future headaches as your project grows and you start to use stores inside these components.
  • view is pretty much equivalent to memo if you don't use any stores. That is nearly always nice to have.

A single reactive component may use multiple stores inside its render.

import React from 'react';
import { view, store } from '@risingstack/react-easy-state';

const user = store({ name: 'Bob' });
const timeline = store({ posts: ['react-easy-state'] });

// this is re-rendered whenever user.name or timeline.posts[0] changes
export default view(() => (
  <div>
    <div>Hello {user.name}!</div>
    <div>Your first post is: {timeline.posts[0]}</div>
  </div>
));

view implements an optimal shouldComponentUpdate (or memo) for your components.

  • Using PureComponent or memo will provide no additional performance benefits.

  • Defining a custom shouldComponentUpdate may rarely provide performance benefits when you apply some use case specific heuristics inside it.

Reactive renders are batched. Multiple synchronous store mutations won't result in multiple re-renders of the same component.

import React from 'react';
import { view, store } from '@risingstack/react-easy-state';

const user = store({ name: 'Bob', age: 30 });

function mutateUser() {
  user.name = 'Ann';
  user.age = 32;
}

// calling `mutateUser` will only trigger a single re-render of the below component
// even though it mutates the store two times in quick succession
export default view(() => (
  <div onClick={mutateUser}>
    name: {user.name}, age: {user.age}
  </div>
));

If you mutate your stores multiple times synchronously from exotic task sources, multiple renders may rarely happen. If you experience performance issues you can batch changes manually with the batch function. batch(fn) executes the passed function immediately and batches any subsequent re-renders until the function execution finishes.

import React from 'react';
import { view, store, batch } from '@risingstack/react-easy-state';

const user = store({ name: 'Bob', age: 30 });

function mutateUser() {
  // this makes sure the state changes will cause maximum one re-render,
  // no matter where this function is getting invoked from
  batch(() => {
    user.name = 'Ann';
    user.age = 32;
  });
}

export default view(() => (
  <div>
    name: {user.name}, age: {user.age}
  </div>
));

NOTE: The React team plans to improve render batching in the future. The batch function and built-in batching may be deprecated and removed in the future in favor of React's own batching.

Always apply view as the latest (innermost) wrapper when you combine it with other Higher Order Components.

import { view } from '@risingstack/react-easy-state';
import { withRouter } from 'react-router-dom';
import { withTheme } from 'styled-components';

const Comp = () => <div>A reactive component</div>;

// DO THIS
withRouter(view(Comp));
withTheme(view(Comp));

// DON'T DO THIS
view(withRouter(Comp));
view(withTheme(Comp));

Usage with (pre v4.4) React Router.

  • If routing is not updated properly, wrap your view(Comp) - with the Routes inside - in withRouter(view(Comp)). This lets react-router know when to update.

  • The order of the HOCs matter, always use withRouter(view(Comp)).

This is not necessary if you use React Router 4.4+. You can find more details and some reasoning about this in this react-router docs page.

Usage with React Developer Tools.

If you want React Developer Tools to recognize your reactive view components' names, you have to pass either a named function or an anonymous function with name inference to the view wrapper.

import React from 'react';
import { view, store } from '@risingstack/react-easy-state';

const user = store({
  name: 'Rick',
});

const componentName = () => (
  <div>{user.name}</div>
);

export default view(componentName);

Passing nested data to third party components.

Third party helpers - like data grids - may consist of many internal components which can not be wrapped by view, but sometimes you would like them to re-render when the passed data mutates. Traditional React components re-render when their props change by reference, so mutating the passed reactive data won't work in these cases. You can solve this issue by deep cloning the observable data before passing it to the component. This creates a new reference for the consuming component on every store mutation.

import React from 'react';
import { view, store } from '@risingstack/react-easy-state';
import Table from 'rc-table';
import cloneDeep from 'lodash/cloneDeep';

const dataStore = store({
  items: [
    {
      product: 'Car',
      value: 12,
    },
  ],
});

export default view(() => (
  <Table data={cloneDeep(dataStore.items)} />
));

Creating local stores

A singleton global store is perfect for something like the current user, but sometimes having local component states is a better fit. Just create a store inside a function component or as a class component property in these cases.

Local stores in function components

import React from 'react'
import { view, store } from '@risingstack/react-easy-state'

export default view(() => {
  const counter = store({ num: 0 })
  const increment = () => counter.num++
  return <button={increment}>{counter.num}</button>
})

Local stores in functions rely on React hooks. They require React and React DOM v16.8+ or React Native v0.59+ to work.

You can use React hooks - including useState - in function components, Easy State won't interfere with them. Consider using autoEffect instead of the useEffect hook for the best experience though.

import React from 'react';
import { view, store } from '@risingstack/react-easy-state';

export default view(() => {
  const [name, setName] = useState('Ann');
  const user = store({ age: 30 });
  return (
    <div>
      <input value={name} onChange={ev => setName(ev.target.value)} />
      <input
        value={user.age}
        onChange={ev => (user.age = ev.target.value)}
      />
    </div>
  );
});

Local stores in class components

import React, { Component } from 'react';
import { view, store } from '@risingstack/react-easy-state';

class Counter extends Component {
  counter = store({ num: 0 });
  increment = () => counter.num++;

  render() {
    return (
      <button onClick={this.increment}>{this.counter.num}</button>
    );
  }
}

export default view(Counter);
You can also use vanilla setState in your class components, Easy State won't interfere with it.

import React, { Component } from 'react';
import { view, store } from '@risingstack/react-easy-state';

class Profile extends Component {
  state = { name: 'Ann' };
  user = store({ age: 30 });

  setName = ev => this.setState({ name: ev.target.value });
  setAge = ev => (this.user.age = ev.target.value);

  render() {
    return (
      <div>
        <input value={this.state.name} onChange={this.setName} />
        <input value={this.user.age} onChange={this.setAge} />
      </div>
    );
  }
}

export default view(Profile);

Don't name local stores as state. It may conflict with linter rules, which guard against direct state mutations.

import React, { Component } from 'react';
import { view, store } from '@risingstack/react-easy-state';

class Profile extends Component {
  // DON'T DO THIS
  state = store({});
  // DO THIS
  user = store({});
  render() {}
}

Deriving local stores from props (getDerivedStateFromProps).

Class components wrapped with view have an extra static deriveStoresFromProps lifecycle method, which works similarly to the vanilla getDerivedStateFromProps.

import React, { Component } from 'react';
import { view, store } from '@risingstack/react-easy-state';

class NameCard extends Component {
  userStore = store({ name: 'Bob' });

  static deriveStoresFromProps(props, userStore) {
    userStore.name = props.name || userStore.name;
  }

  render() {
    return <div>{this.userStore.name}</div>;
  }
}

export default view(NameCard);

Instead of returning an object, you should directly mutate the received stores. If you have multiple local stores on a single component, they are all passed as arguments - in their definition order - after the first props argument.

Advanced Usage 🤓

Adding side effects

Use autoEffect to react with automatic side effect to your store changes. Auto effects should contain end-of-chain logic - like changing the document title or saving data to LocalStorage. view is a special auto effect that does rendering.

Never use auto effects to derive data from other data. Use dynamic getters instead.

import { store, autoEffect } from '@risingstack/react-easy-state';

// DON'T DO THIS
const store1 = store({ name: 'Store 1' })
const store2 = store({ name: 'Store 2' })
autoEffect(() => store2.name = store1.name)

// DO THIS INSTEAD
const store1 = store({ name: 'Store 1' })
const store2 = store({ get name () { return store1.name } })

Global auto effects

Global auto effects can be created with autoEffect and cleared up with clearEffect.

import { store, autoEffect, clearEffect } from '@risingstack/react-easy-state';

const app = store({ name: 'My App' })
const effect = autoEffect(() => document.title = app.name)

// this also updates the document title
app.name = 'My Awesome App'

clearEffect(effect)
// this won't update the document title, the effect is cleared
app.name = 'My App'

Local auto effects in function components

Use local auto effects in function components instead of the useEffect hook when reactive stores are used inside them. These local effects are automatically cleared when the component unmounts.

import React from 'react'
import { store, view, autoEffect } from '@risingstack/react-easy-state';

export default view(() => {
  const app = store({ name: 'My App' })
  // no need to clear the effect
  autoEffect(() => document.title = app.name)
})
Explicitly pass none reactive dependencies - like vanillas props and state - to local auto effects in function components.

Because of the design of React hooks you have to explicitly pass all none reactive data to a hook-like dependency array. This makes sure that the effect also runs when the none reactive data changes.

import React from 'react'
import { store, view, autoEffect } from '@risingstack/react-easy-state';

export default view(({ greeting }) => {
  const app = store({ name: 'My App' })
  // pass `greeting` in the dependency array because it is not coming from a store
  autoEffect(() => document.title = `${greeting} ${app.name}`, [greeting])
})

Local auto effects in class components

Local effects in class components must be cleared when the component unmounts.

import React, { Component } from 'react'
import { store, view, autoEffect } from '@risingstack/react-easy-state';

class App extends Component {
  app = store({ name: 'My App' })

  componentDidMount () {
    this.effect = autoEffect(() => document.title = this.app.name)
  }

  componentWillUnmount () {
    // local effects in class components must be cleared on unmount
    clearEffect(this.effect)
  }
}

API Summary 📖

store(obj)

Creates an observable store from the passed object and returns it. Can be used outside components for global stores and inside components for local stores.

import { store } from '@risingstack/react-easy-state';

const user = store({ name: 'Rick' });

view(Comp)

Creates a reactive view from the passed component and returns it. A reactive view re-renders whenever any store data used inside it is mutated.

import React from 'react';
import { view, store } from '@risingstack/react-easy-state';

const user = store({ name: 'Bob' });

export default view(() => (
  <div>Hello {user.name}!</div>
));

batch(fn)

Immediately executes the passed function and batches all store mutations inside it. Batched mutations are guaranteed to not trigger unnecessary double renders. Most task sources are batched automatically, only use batch if you encounter performance issues.

import React from 'react';
import { view, store } from '@risingstack/react-easy-state';

const user = store({ name: 'Bob' });

function setName() {
  batch(() => {
    user.name = 'Rick'
    user.name = 'Ann'
  })
}

autoEffect(fn)

Creates a reactive function from the passed one, immediately executes it, and returns it. A reactive function automatically re-reruns whenever any store data used inside it is mutated.

Can be used both outside and inside components.

import { store, autoEffect } from '@risingstack/react-easy-state';

const user = store({ name: 'Bob' })

autoEffect(() => document.title = user.name)

clearEffect(fn)

Takes a reactive function (returned by autoEffect) and clears the reactivity from it. Cleared reactive functions will no longer re-rerun on related store mutations. Reactive functions created inside function components are automatically cleared when the component unmounts.

import { store, autoEffect, clearEffect } from '@risingstack/react-easy-state';

const user = store({ name: 'Bob' })

const effect = autoEffect(() => document.title = user.name)
clearEffect(effect)

Examples with live demos 📺

Beginner

Advanced

Articles 📢

Performance 🚀

You can compare Easy State with plain React and other state management libraries with the below benchmarks. It performs a bit better than MobX and similarly to Redux.

Platform support 💻

  • Node: 6 and above
  • Chrome: 49 and above
  • Firefox: 38 and above
  • Safari: 10 and above
  • Edge: 12 and above
  • Opera: 36 and above
  • React Native: 0.59 and above

This library is based on non polyfillable ES6 Proxies. Because of this, it will never support IE.

Alternative builds 🔧

This library detects if you use ES6 or commonJS modules and serve the right format to you. The default bundles use ES6 features, which may not yet be supported by some minifier tools. If you experience issues during the build process, you can switch to one of the ES5 builds from below.

  • @risingstack/react-easy-state/dist/es.es6.js exposes an ES6 build with ES6 modules.
  • @risingstack/react-easy-state/dist/es.es5.js exposes an ES5 build with ES6 modules.
  • @risingstack/react-easy-state/dist/cjs.es6.js exposes an ES6 build with commonJS modules.
  • @risingstack/react-easy-state/dist/cjs.es5.js exposes an ES5 build with commonJS modules.

If you use a bundler, set up an alias for @risingstack/react-easy-state to point to your desired build. You can learn how to do it with webpack here and with rollup here.

Contributors ✨

Contributions are always welcome, please read our contributing documentation.

Thanks goes to these wonderful people (emoji key):


Miklos Bertalan

💻 ⚠️ 📖 📝

Roland

💻 ⚠️ 📖

Daniel Gergely

💻 🎨 💡

Peter Czibik

🚇

This project follows the all-contributors specification. Contributions of any kind welcome!

More Repositories

1

graffiti

⚠️ DEVELOPMENT DISCONTINUED - Node.js GraphQL ORM
JavaScript
1,009
star
2

node-style-guide

A mostly reasonable approach to JavaScript - how we write Node.js at RisingStack
992
star
3

graphql-server

Example GraphQL server with Mongoose (MongoDB) and Node.js
JavaScript
846
star
4

risingstack-bootcamp

This is the Node.js Bootcamp we ask new recruits at RisingStack to finish in their first weeks. It helps to get the basics right, and prepare you to work on enterprise projects.
JavaScript
703
star
5

multi-process-nodejs-example

JavaScript
516
star
6

trace-nodejs

Trace is a visualised distributed tracing platform designed for microservices.
JavaScript
471
star
7

protect

Proactively protect your Node.js web services
JavaScript
401
star
8

graffiti-mongoose

⚠️ DEVELOPMENT DISCONTINUED - Mongoose (MongoDB) adapter for graffiti (Node.js GraphQL ORM)
JavaScript
382
star
9

node-typescript-starter

TypeScript
351
star
10

react-way-getting-started

The React Way: Getting Started
JavaScript
343
star
11

example-prometheus-nodejs

Prometheus monitoring example with Node.js
JavaScript
332
star
12

nodehero-authentication

JavaScript
231
star
13

react-way-immutable-flux

React.js way with ES6, Immutable.js and Flux
JavaScript
224
star
14

kubernetes-graceful-shutdown-example

Example app for graceful start and stop with Kubernetes and Node.js
JavaScript
167
star
15

kubernetes-nodejs-example

Node.js example application with Kubernetes and CircleCI config
JavaScript
149
star
16

opentracing-auto

Out of the box distributed tracing for Node.js applications with OpenTracing.
JavaScript
133
star
17

http2-push-example

HTTP/2 Push example
JavaScript
129
star
18

event-sourcing-example

Event Sourcing Example repo for the Node.js at Scale blog series
JavaScript
87
star
19

node-with-rust

JavaScript
87
star
20

cqrs-example

CQRS: Command Query Responsibility Segregation - Node.js at Scale
JavaScript
83
star
21

koa-prerender

KOA middleware for prerendering javascript-rendered pages on the fly for SEO
JavaScript
77
star
22

react-baby-steps

Zero to Redux through Flux (with Rx) in baby steps
JavaScript
67
star
23

jaeger-node

Out of the box distributed tracing for Node.js applications.
JavaScript
67
star
24

mysql-large-data-handling

Code for the blogpost about handling large amount of data in Node
JavaScript
60
star
25

graffiti-todo

Example Relay TodoMVC application using graffiti-mongoose
JavaScript
58
star
26

example-http-timings

Example HTTP Timings in Node.js
JavaScript
50
star
27

example-kubernetes-nodejs

Introduction to Kubernetes with Node.js
JavaScript
50
star
28

training-microservices

Node.js Microservices training
49
star
29

docker-node

Dockerfiles for running Node.js
JavaScript
45
star
30

writing-testable-apis-the-basics

Writing testable HTTP APIs - the basics
JavaScript
43
star
31

anchor

Turns Kubernetes resources into a Helm chart
JavaScript
38
star
32

nodehero-testing

JavaScript
37
star
33

pact-example

This is an example of using pact-js with node.
JavaScript
34
star
34

Swiftify-iOS

Run Node.js code with Browserify on iOS
Swift
28
star
35

colorblinder

An example React-Native game for the series "Learning React-Native as a React developer: a definitive guide".
JavaScript
28
star
36

webinar-kubernetes-api-gateway

Microservices​ ​with​ ​Node.js​ ​and​ ​Kubernetes​
JavaScript
26
star
37

training-microservices-v3

Microservices training
JavaScript
19
star
38

opentracing-infrastructure-graph

Infrastructure visualisation via OpenTracing instrumentation
JavaScript
16
star
39

debug-node-docker

Code of the "How to debug a Node app in a Docker container" post on https://blog.risingstack.com
JavaScript
14
star
40

docker-codeship-project

JavaScript
13
star
41

opentracing-metrics-tracer

Exports cross-process metrics via OpenTracing to Prometheus.
JavaScript
13
star
42

nodejs-at-scale-handling-async

Article examples to handle async for the Node.js at Scale series.
JavaScript
12
star
43

thorken

Redis based JWT session for Node.js with the power of Thor
JavaScript
11
star
44

trace-go

Trace is a visualised stack trace platform designed for microservices.
Go
11
star
45

react-training

JavaScript
8
star
46

golang-tutorial-for-nodejs-developers-getting-started

This is the reference implematition for the "Golang Tutorial for Node.js Developers, Part I.: Getting started" blogpost at https://blog.risingstack.com/golang-tutorial-for-nodejs-developers-getting-started/
Go
8
star
47

post-stripe

Blog post about Stripe and Webshops: https://blog.risingstack.com/stripe-payments-integration-tutorial-javascript/
JavaScript
8
star
48

nrs

nsr - npm registry switcher
JavaScript
7
star
49

training-microservices-v2

Microservices training
JavaScript
7
star
50

post-stripe-api

API for Blog post about Stripe and Webshops: https://blog.risingstack.com/stripe-payments-integration-tutorial-javascript/
JavaScript
7
star
51

kubernetes-training

Shell
6
star
52

rising-url

Extends require('url').format() with parameters and easier inputs
JavaScript
6
star
53

auth0-ts-vue-example

Example repository for setting up Auth0 for Vue apps with TypeScript
TypeScript
6
star
54

cache

Stale / Expire Cache Implementation
JavaScript
6
star
55

rate-limiter

Rolling rate limiter
JavaScript
6
star
56

your-first-browserify-module

JavaScript
5
star
57

nuxt3-rendering-modes

Rendering modes showcase for nuxt 3
Vue
5
star
58

easy-state-hook-examples

Notes for a blogpost, nothing to see here (yet).
HTML
5
star
59

learnyougo

Go
5
star
60

surviving-web-security

Showcase for some of the Node.js / Web Security Best Practices
JavaScript
4
star
61

kubernetes-prometheus-nodejs

Monitoring with prometheus example
JavaScript
4
star
62

node-community-convention-training

JavaScript
3
star
63

endava_node

JavaScript
3
star
64

last-release-git-tag

GitHub Plugin for semantic-release
JavaScript
3
star
65

node-basics-skeleton

JavaScript
3
star
66

aha-news

TypeScript
3
star
67

oneshot-contest

JavaScript
3
star
68

shapeblinder

Fun demo project for the 2020 Dart and Flutter crash course series
Dart
3
star
69

profiler

JavaScript
3
star
70

expense_tracker

Expense tracker app
JavaScript
2
star
71

react-hooks-meetup

JavaScript
2
star
72

ncc-training

node community convention training
JavaScript
2
star
73

docker-node-base

JavaScript
1
star
74

find-port

Open port finder with Promise interface.
JavaScript
1
star
75

distributed-loadtests-jmeter

HCL
1
star
76

bc-node-example

JavaScript
1
star
77

node-hero-webinar-demo-app-authentication

1
star
78

almandite-user-service

Reference implementation of a user authentication service in GOlang!
Go
1
star
79

jsconfbp-2019-graphql

JavaScript
1
star
80

hwsw-adatbazis_muveletek

JavaScript
1
star
81

trace-cli

CLI for Trace by RisingStack: deployhook
JavaScript
1
star
82

silver-giggle

JavaScript
1
star
83

hwsw-react

JavaScript
1
star
84

demo-api

Demo Node API for testing your frontend's HTTP capabilities.
JavaScript
1
star
85

nuxt3-caching-with-auth

Demonstrate SWR and ISR rendering modes usage with auth
Vue
1
star