Giter Club home page Giter Club logo

react-easy-state's Introduction

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!

react-easy-state's People

Contributors

18thletter avatar allcontributors[bot] avatar brianrosamilia avatar buzinas avatar dan-gamble avatar dnlgrgly avatar f-adam-b avatar kubischj avatar moritzuehling avatar peteyycz avatar pontusab avatar rolandszoke avatar solkimicreb avatar stephanlough 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  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

react-easy-state's Issues

TypeScript class support

Is there a way to get this to work with TS classes? It works if you use it as a function:

const View1 = ez.view(() => <div>{appState.count}</div>);

However I haven't been able to get it to work with class, e.g.:

class View2 extends React.Component<{count:number}, {}>{
	public render() {
		return <div>Hello from View2 {this.props.count}</div>;
	}
}

const View3 = ez.view(View2);

That gives me:

Uncaught TypeError: Class constructor View2 cannot be invoked without 'new'
    at new ReactiveHOC (es.es5.js:27)
    at constructClassInstance (react-dom.development.js:6801)
    at updateClassComponent (react-dom.development.js:8336)
    at beginWork (react-dom.development.js:8982)
    at performUnitOfWork (react-dom.development.js:11814)
    at workLoop (react-dom.development.js:11843)
    at HTMLUnknownElement.callCallback (react-dom.development.js:100)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:138)
    at invokeGuardedCallback (react-dom.development.js:187)
    at replayUnitOfWork (react-dom.development.js:11318)

I tried making a decorator but haven't figured that out yet unfortunately, all sorts of typing problems (I haven't done anything with decorators yet), but that seems like the ideal way to use it... In case it helps, my tsconfig.json is:

{
	"compilerOptions": {
		"experimentalDecorators": true,
		"jsx": "react",
		"moduleResolution": "node",
		"target": "es6"
	},
	"include": [
		"src/app/ts/*.ts",
		"src/app/tsx/*.tsx"
	]
}

Extending Store in Typescript

Hi,

I am new to Typescript and this may be more appropriate question in a TS forum. However, while using react-easy-state in TS, I am not able to import its types, e.g. Store from the library. I need to extend my application's store, the use case is to define a common interface AppStore with well defined methods and properties. To achieve this, I am trying to extend the Store type and hence this issue.

Any suggestions? I thought the use case is simple enough to not warrant code, but would be glad to add some if needed.

Thanks!

Hook into proxy

I have a wish/suggestion to always do Store.x = 5 instead of Store.setX(5)
But upon this setting I want to do something before or after setting.
I know setters intended for this, but then I have to call it different name than the property....
Maybe it is not good writing, maybe I should do always setX(), everybody doing like this... Please advise

For example if I set todos[i].new = true
Then I trigger some function inside the store.

Could/Should I tap into your Proxy somehow ? Is it called middleware ?

view HoC is blocking react-router V4

I've been putting together an application and noticed this morning that when I have a component wrapped with view, it loses the ability to work with react router v4.

After some digging, it appears as though this bit of documentation explains what's happening.

I've been able to patch around this by wrapping my components using their withRouter HoC or wrapping the component in an empty <Route />, but apparently this is redundant and not optimal according to their documentation. Is there any way this project can propagate whatever react router (and likely others) needs to continue functioning?

TypeScript Support

Hey,

i would like to use this react with TypeScript and EasyState. I followed the tutorial on https://www.typescriptlang.org/docs/handbook/react-&-webpack.html, but unfortunately i don't get it to work. I've imported the easyState.js in my index.html and defined it as external in the webpack.config.js...
Actually i don't have any experiences with webpack. So maybe anyone can help me?!

Thanks in regard.

Discourage direct mutation to global store.

In the contacts example the Contact component mutates the global store directly by doing

 Object.assign(this.props.contact, this.store.currentContact)

I assume it is for demonstration purpose for letting the users know that 'direct mutations' works too and that's great but according to the general practice direct mutation are bad for real life apps and there should be a function for it like you have for onDelete .

 store.deleteContact(this.props.contact)

I just want to suggest that wouldn't it be better to add a warning as comments in the code example or in the main readme saying that 'Though direct mutation to global store from a component works but it's not recommended as a general practice.'
Anyway nice library. 👍

Modules and actions

Lovely little library, nicely done.

I have just a few questions about how I might integrate it into a decently-sized app. It would be good to see examples of how these things might be done:

  1. Vuex has the concept of modules, where you can keep functionality modular, but also communicate between modules (via root) to wire an app together. I'm wondering how this might be done in react-easy-state -an example of an app with multiple stores to explain this more clearly would be great.

  2. The actions seem a bit cumbersome, having to reference the store by name seems to mean that you can't define actions separately and then include them in a "config" that creates a store. So I'm wondering if a store basically needs to be a huge file with all actions inside. This kind of separation would be most welcome.

Highlight platform support

Hi there!

Thanks for your great work on this library, looks really neat!

I have a concern, though. I feel like the "Platform Support" is burying the lede a bit... I imagine many devs will just assume that a React state library won't have any browser-support issues (because most JS is polyfill-able, the "common" browser-support concerns are things that touch the DOM, like styling).

I think it's a realistic scenario that someone might create a new app, spend 3 months building it out, and then right before release decide to test it on legacy browsers, only to discover that it's totally broken, and they have to perform a massive refactor to switch to a different state lib to get it to work.

I'm not saying you'd be to blame in this situation: you do make this point clear in the README. But, you know, not everyone reads documentation in its entirely. Especially newer developers who aren't familiar with ES proxies would be susceptible to this.

I think if we pulled the "Platform Support" section to the top, near "Installation", we reduce the risk of this happening dramatically. We could also bold the text about No IE Support

Also, this is a nit, but I think it's a bit disingenuous to say that "This may change in the future, if these platforms add ES6 Proxy support.", since Microsoft will never release another IE, so this will be perpetually broken in IE.

Happy to open a PR if you agree with me!

fuzzy search with fuse.js not updating in view

Has any one used react-easy-state with fuse.js for a fuzzy search?

http://fusejs.io/

  1. I assign a store to do a cities fuzzy search
    const localStore = store({ cities: [], displayedCities:[], name:'thing'});

  2. have a fuzzy filter on keydown in the input. Logging the localStore shows the expected out put, by UI won't show changes in the array. Athough will update localStore.name..
    `
    fuzzyFilter(event){
    let value = event.target.value;
    var options = {
    keys: ['name']
    }
    var fuse = new Fuse(localStore.displayedCities , options)

    let result = fuse.search(value)
    console.log(result);
    localStore.displayedCities = result;

    localStore.name = value;
    console.log(localStore);

    }

`

any ideas?

Using this.setState doesn't trigger a re-render. Intentional?

Hi! Awesome library, trying to use it in my project now and realised that using the 'vanilla' component state doesn't seem to work. Is that intended, do I simply use a local store for my component for the same functionality?

if it's intended, perhaps it's worth including that component state shouldn't be used more explicitly in the docs (for people like me)?

React components not updating on store change

There is a good chance this is a just me issue. But I've been trying to figure out what's going on for a while with no success.

When I update my store, my components won't auto update to recognise the change.

Full repo: https://github.com/ro-savage/the-places-you-will-go
Code Sandbox: https://codesandbox.io/s/github/ro-savage/the-places-you-will-go
(react-easy-state 4.1.2, React 16.2, CRA 1.1.1)

Store

import { store } from 'react-easy-state'

const destinations = {
  add: (destination) => { 
    destinations.list.push(destination); 
    console.log(destination, destinations.list)
  },
  new: '',
  list: [
    'Canberra',
    'Auckland',
    'Berlin',
  ]
}

export default store(destinations)

Listing an array

import React from 'react'
import { view } from 'react-easy-state'

import destinations from '../destinationsStore.js'

const ListDestination = () => {
  return (
    <ul>
      {destinations.list.map(destination => {
        return (
          <li key={destination}>{destination}</li>
        )
      })}
    </ul>
  )
}

export default view(ListDestination)

Adding to array

import React from 'react'
import { view } from 'react-easy-state'

import destinations from '../destinationsStore.js'

const AddDestination = () => {
  const onClick = () => {
    destinations.add(destinations.new)
    destinations.new = ''
  }
  return (
    <div>
      <div>Choose a destination</div>
      <input 
          type="text" placeholder="Destination" 
          onChange={(e) => {destinations.new = e.target.value}} 
          value={destinations.new} 
       />
      <button onClick={onClick}>Add Destination</button>
    </div>
  )
}

export default view(AddDestination)

App

import React, { Component } from "react"
import "./App.css"

import { view } from 'react-easy-state'
import AddDestination from './destinations/AddDestination/AddDestination';
import ListDestinations from './destinations/ListDestinations/ListDestinations';


class App extends Component {
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <AddDestination />
          <ListDestinations />
        </header>
      </div>
    )
  }
}

export default view(App)

Production ready

Heya, first i want to mention that i love the library and it's very easy and fun to use it, but my question would be is anybody using it for an in production and what are the experiences with it. Also i see there is no development on the repo for a while so is this like dead, that would suck really bad.

No `jsnext:main` section?

A jsnext:main field that points to the ES6 version of the library's code. I see that package.json has the module field, but it points to the ES5 (transpiled?) code.

Setting global store

I have global store like this:

const Store = easyStore({
  loading: false
});

Then I want to show loading component, I set Store.loading = true.
Indeed loading shows up.
Then after some procedure or after just delay I set Store.loading = false
And ... no reaction, no rerender.

I do the same inside setTimeout(() => ..., 1000)
And ... it rerenders correctly

I have no clue ... :)

Are there any plans for a "strict mode"?

Really liking this library, but I have one concern about using it in a larger codebase. Specifically I want to prevent mutations from happening outside store({}). I've been using Mobx (which has this functionality) but I'd happily switch over if something like this was included.

Example:

import { store, useStrict } from 'react-easy-state'

useStrict()

const counter = store({
  count: 0,
  increment() {
   this.count += 1
  }
})

counter.count++ // fails w/ warning

counter.increment() // works

Seeing some odd issues after updating to 5.0.0 from 4.1.2

I know auto-bind was removed but did this change how stores behave? I wrote my own auto-bind once I saw that it was going to be removed but my stores appear to have some issues after the update. Read the release notes and it didn't mention any particular changes to stores but I see that the 'store.js' file is now gone and is now just exporting a plain observable. I think this may be a breaking change.

Suggestion: Passing observable store as props

You may have already thought of this / decided it was a bad idea. My understanding of how all this works it pretty damn basic (never used observables or MobX/Reactive Framework)

What if you passed the observable as a prop to the component, so that you can still use propTypes and this behave a bit more as 'normal' react.

For example

import React from 'react'
import PropTypes from 'prop-types'
import { view } from 'react-easy-state'
import destinations from '../destinationsStore.js'

const ListDestination = (props) => {
  return (
    <ul>
      {props.destinations.list.map(destination => {
        return (
          <li key={destination}>{destination}</li>
        )
      })}
    </ul>
  )
}

ListDestination.propTypes = {
  destinations: PropTypes.shape({
    list: PropTypes.array,
  }),
}

export default view(ListDestination, {destinations})

💡 Features from Redux that I would like to see in react-easy-state

Here are a few things that I like from Redux that I think could enhance this great lib:

  • Single global store: it is very useful to have access to the whole store from any part of the application. Perhaps some documentation on how to do this properly would be useful.
  • Action log: in Redux I am able to console.log any action type in any reducer. This is very useful for debugging.

I made a simple counter app with this library and I really like it. I am considering rebuilding a work project to react using this state management library. Great work!

Store functions vs separate ones

Hey, @solkimicreb

I've just discovered this library and decided to replace a few reducers and redux with it in my current project. Managed to do it with no difficulties and so far it works well. I've got a simple question, maybe opinionated:

const notificationsStore = store({
  notifications: [],
  addNotification (message) {
    notificationsStore.notifications.push(message)
  }
})

vs

const notificationsStore = store([])

function addNotification(message) {
  notificationsStore.push(message)
}

What do you think about this one, any pros/cons? What's your advice on this one?

create-react-app production build fails

Command: npm run build

Output:

> react-scripts build
3:44:35 PM: Creating an optimized production build...
3:44:43 PM: Failed to compile.
3:44:43 PM: Failed to minify the code from this file: 

./node_modules/@nx-js/observer-util/src/observer.js:8 

Read more here: http://bit.ly/2tRViJ9
3:44:43 PM:
3:44:43 PM: Build complete: exit code: 1
3:44:43 PM:
3:44:44 PM: Cleaning up docker container
3:44:44 PM: npm
3:44:44 PM:
3:44:44 PM: ERR!
3:44:44 PM: Linux 3.19.0-66-generic
3:44:44 PM: npm
3:44:44 PM:
3:44:44 PM: ERR!
3:44:44 PM: argv "/opt/buildhome/.nvm/versions/node/v6.11.2/bin/node" "/opt/buildhome/.nvm/versions/node/v6.11.2/bin/npm" "run" "build"
3:44:44 PM: npm
3:44:44 PM: ERR! node
3:44:44 PM: v6.11.2
npm
3:44:44 PM:
3:44:44 PM: Error running command: Build script returned non-zero exit code: 1
3:44:45 PM: ERR! npm v3.10.10
3:44:45 PM: npm
3:44:45 PM: ERR!
3:44:45 PM: An error occurred while building the site, skipping the deploy and cache refresh.
3:44:45 PM: code ELIFECYCLE
3:44:45 PM: npm ERR!
3:44:45 PM: [email protected] build: `react-scripts build`
npm
3:44:45 PM: ERR!
3:44:45 PM: Build script returned non-zero exit code: 1
3:44:45 PM: Exit status 1
npm
3:44:45 PM: ERR!
3:44:45 PM: npm
3:44:45 PM: ERR!
3:44:45 PM: Failed at the [email protected] build script 'react-scripts build'.
3:44:45 PM: npm ERR!
3:44:45 PM: Make sure you have the latest version of node.js and npm installed.
3:44:46 PM: npm ERR!
3:44:46 PM: If you do, this is most likely a problem with the rep-counter-client package,
npm
3:44:46 PM:
3:44:46 PM: ERR!
3:44:46 PM: not with npm itself.
npm
3:44:46 PM:
3:44:46 PM: ERR!
3:44:46 PM: Tell the author that this fails on your system:
npm ERR! react-scripts build
npm ERR!
3:44:46 PM: You can get information on how to open an issue for this project with:
3:44:46 PM: npm ERR!
3:44:46 PM: Finished processing build request in 49.305966188s
3:44:46 PM: npm bugs rep-counter-client
3:44:46 PM: npm
3:44:46 PM: ERR!
3:44:47 PM: Or if that isn't available, you can get their info via:
npm
3:44:47 PM: ERR!
3:44:47 PM: npm owner ls rep-counter-client
3:44:47 PM: npm
3:44:47 PM: ERR!
3:44:47 PM: There is likely additional logging output above.
3:44:47 PM:
3:44:47 PM: npm
3:44:47 PM: ERR! Please include the following file with any support request:
npm
3:44:47 PM: ERR! /opt/build/repo/npm-debug.log
3:44:47 PM: Cached NPM modules

Type definitions

would be cool to have typings for typescript
at least like so:

declare module 'react-easy-state' {
  export function store(obj: any): any;

  export function view(Comp: any, ref: any): any;

  export namespace store {
    const prototype: {};
  }

  export namespace view {
    const prototype: {};
  }
}

Batch store updates

Hi there,

Thanks so much for this awesome library, loving the drop and go nature of it.

One issue I am facing at the moment is that of making store updates and those updates are triggering a render on each and every property I update. I would like to be able to batch an update to the store, i.e. edit multiple individual properties before it triggers its re-render of the view.

I'm currently using it like this:

export const UserStateStore = store<IUserStateStore>({
  initialUserCheckRan: false,
  isLoggedIn: false,
  user: {
    authLevels: [EAuthLevel.ANONYMOUS],
    photoUrl: null,
    username: "",
    email: "",
    uid: "",
    authNodeIds: [],
  },
  loginUser(user) {
    UserStateStore.user = user;
    UserStateStore.isLoggedIn = true;
    UserStateStore.initialUserCheckRan = true;
  }
});

As you can see I have that loginUser() function there. When that is called I'd like to update the user object, and the logged in state and set that our initial check for a currently logged in user has been run.

But each of those three changes are triggering a re-render in my view which is set to listen for those properties.

Is there anything in react-easy-state which works similar to mobx actions? I recall the actions in MobX waiting until the action function has finished before updating views.

Persistence

How do you handle persistence of store objects? is there anything like redux persist? or do you have any suggestions about how to handle it?

Deriving a store from props

My issue copied from Reddit.

What would be the solution to make Easy State work similar to getDerivedStateFromProps? What if I wanted a child component to update the store depending on the props passed from a parent component?

class Parent extends Component {
  store = store({ number: Math.random() });

  handleButtonClick = () => {
      this.store.number = Math.random();
  };

  render() {
      return (
          <div>
              <button onClick={this.handleButtonClick}>Generate Random Number</button>                
              <Child number={this.store.number} />
          </div>
      );
  }
}

class Child extends Component {
  store = store({
      // number needs to update based on the number prop passed from parent on will receive props
      number: this.props.number + 1,
  });

  render() {
      return <div>{this.store.number}</div>;
  }
}

How to derive a store from props on will receive props?


solkimicreb
Ouch, I didn't think about that change :D I guess I could make it work exactly like it is now with two differences.

It would get the first local store on the component as the second argument, instead of the state.
It would merge the returned object with the first local store on the component, instead of the state.
Your example would look like this:

class Child extends Component {
  store = store({
    number: this.props.number + 1
  });

  static getDerivedStateFromProps (props, store) {
    return { number: this.props.number + 1 };
  }

  render() {
    return <div>{this.store.number}</div>;
  }
}

This would place a few (tiny) restrictions on components with getDerivedStateFromProps.

These components should not have more than one local store to avoid confusion (of which store would receive the update object from getDerivedStateFromProps).
These components should not use vanilla React state in concjuction with local stores to avoid the above confusion.
Do you think this would be okay? Thanks for the catch (:

Edit: another approach would be to keep the exact current behavior with props and state and pass in a third argument, which is an array of local stores. Those stores could be mutated directly in the function, while the return value would be merged with state (as it is right now.) This feels a bit dirtier, but it would only extend the current behavior, instead of replacing some of it. Would this be better?

Edit2: I think I vouch for the first one, as the restrictions in places are also best practices. It might be beneficial to enforce them.

Store JSX in Store.

Hey,

first of all, thanks for this great library. I started tinkering with it a bit and I have encountered an interesting error.

When I try to set jsx in an object like so:
let myObj = {test: <span>Test</span>};
then I can interpolate this object in my views just fine.

But when I wrap myObj in a store and try to call it, I get the following error:

TypeError: 'get' on proxy: property '_store' is a read-only and non-configurable data property on the proxy target but the proxy did not return its actual value (expected '#<Object>' but got '[object Object]')

This error occurs in react in

  1132 |   }
  1133 | } else if (isValidElement(node)) {
  1134 |   // This element was passed in a valid location.
> 1135 |   if (node._store) {
  1136 |     node._store.validated = true;
  1137 |   }
  1138 | } else if (node) {

So I guess I can't store JSX in a Store. Is there any way around this?

make autobind optional

I'm really liking the compact state management, however I'm not sure I want my methods to be automagically bound to the class instance.

Maybe something like export default view(HelloComp, { autoBind: true }) could be used to explicitly enable this feature?

Hierarchical multi store

This is just my implementation for review.
Included the self workaround + observable in each sub-store. In order to access sub-store from inside.
Tried with classes, like in mobx, didn't work.

import { observable } from 'lib/observable'
import EndOfCall from './EndOfCall'

const Store = {
    EndOfCall,
    averageRating: 4,
}

export default observable(Store)
import navigate from './Navigate'
import { observable } from 'lib/observable'

const EndOfCall = {
    navigate,
}

const self = observable(EndOfCall)
export default self
import Store from 'Store'
import { observable } from 'lib/observable'

const navigate = {
    name: '',
    address: '',
    phone: '',

    get averageRating() {
        return Store.averageRating
    },

    setRating(e) {
        self.rating = e.target.value
    },

    get google() {
        return 'https://' + encodeURI(self.address)
    },

}

const self = observable(navigate)
export default self

Proxies polyfill

Hi,

As stated in the docs "This library is based on non polyfillable ES6 Proxies. Because of this, it will never support IE". Looking at something like proxy-polyfill, proxies seems to already have some polyfill to handle IE9+ support.

Is there a reason why this polyfill would not work with react-easy-state? (which part is non polyfillable, and is this for ever?)

ps. thanks for the great work: the simplicity of react-easy-state is a breeze!

() => {

Hi,

I am starting to use it and I am amazed how much it saves comparing to using react state!
Love Proxy and what you are doing!

Small stuff:
Apparently declaring functions in the store with () => { does not work. The this no right.
Is it fixable ? I love these short expressions...

Thanks

Middlewares support

Hey.
I really like react-easy-state, it is easy enough to work with, simple, clean and not messy like redux or mobx.
One thing i really liked about redux is the fact you can pass middlewares, for example I can pass an error-logger middleware which logs all new state changes and in case of an error in the users browser i take a snapshot of all the stores, the input and operations the user did and try to recreate it to fix the bugs.
Are there plans for adding middlewares in the future or should I just wrap all my stores and call one function that does what I need instead ?

const { store }  = 'react-easy-state'

const UserStore = store({
    name:'',
    lastName:''
})

const OtherStore = store({
    otherName:'',
    otherLastName:'',
    updateUserName:function(name){
        console.log('updating with name', name)
        OtherStore.name = name
    }
})

const loggerMiddleware = (...args) => {
    console.log(`this is logger middleware`, args)
}

const otherMiddleware = (...args) => {
    console.log(`this is other middleware`, args)
}

// if array, map on it, if object get keys and map on it
const map = (toIterateOver,func) => {
    return Array.isArray(toIterateOver) ? 
        toIterateOver.map(func) : 
        typeof toIterateOver === 'object' ? 
        Object.keys(toIterateOver).map(func) : 
        void(0)
}

// apply middleware func
const applyMiddleware = (middlewares, store, prop)=>{
    // copy old function
    const oldFunc = store[prop].bind(null)
    // overwrite function to apply middlewares, then, call original function with original args
    store[prop] = async function (...args){
        console.log(arguments)
        for(let middleware of middlewares){
            await middleware(...args)
        }
        oldFunc.call(null, ...args)
    }
}

// pass middlewares and stores
const createStores = helperMapFunc => (...middlewares) => (...stores) => {
    // map on stores
    helperMapFunc(stores, storeObject=>{
        // map on store props
        helperMapFunc(storeObject, prop=>{
            // if store has own prop and it is func apply middlewares
            storeObject.hasOwnProperty(prop) && typeof storeObject[prop] === 'function' && applyMiddleware(middlewares, storeObject, prop)         
        })
    })
    // return stores for usage
    return {
        ...stores
    }
}

export default createStores(map)(loggerMiddleware, otherMiddleware)(UserStore, OtherStore)

TypeScript Typings, again

Issue #4 was mistakenly closed due to a misunderstanding as to what "TypeScript support" implies.

It isn't that special steps are required to use this library with TypeScript and/or WebPack. That's unrelated to what #4 was implying.

The request came about because there are no typings available so when you use this library with TypeScript, no hinting is available. This is also an issue when you have no-implicit-any enabled as that prevents you from importing the library.

Most TypeScript projects will have no-implicit-any enabled as that's largely the whole point of TypeScript -- to avoid having untyped references in your code!

Anyway -- what would be great is if this project's author created a .d.ts file and added it to this repository. The .d.ts file is kind of like a c header file that contains the definition of the signatures of any types exported by this library.

Again, issue #4 was closed in error based on a misunderstanding of both TypeScript and its ecosystem.

`view` cannot copy static defaultProps getter

const defaultProps = { number: 0 };
let id = 0;

class SubComponent extends Component {
  static get defaultProps() {
    return { ...defaultProps, id: id++ };
  }

  // Other methods
}

export default view(SubComponent);

This throws an error for me: Uncaught TypeError: Cannot set property defaultProps of ...
It looks like view(BaseComponent) can't copy a static getter property.
Here is a Codesandbox link to an example of the error: https://codesandbox.io/s/x209v97ypq

MDN error link.

Is there a way to solve this?


Edit 1

Was just looking at view.js again. Could ReactiveHOC extend the passed in argument Comp instead of BaseComp? If so, would it still be necessary to copy the static properties to ReactiveHOC if it extended the Comp argument?

return class ReactiveHOC extends BaseComp {
    static displayName = Comp.displayName || Comp.name;
    static contextTypes = Comp.contextTypes;
    static childContextTypes = Comp.childContextTypes;
    static propTypes = Comp.propTypes;
    static defaultProps = Comp.defaultProps;
    ...
}

Could that just be

return class ReactiveHOC extends Comp {
    ...
}

?


Edit 2

Nvm my question in Edit 1. I realized that making a HOC extending a functional component does not necessarily make it extend React.Component.

Would it be possible to check the value isStatelessComponent before copying the static properties?
So if isStatelessComponent is true, copy the static properties, otherwise make ReactiveHOC extend from Comp without copying static properties..?

Explain why everything must be wrapped

Multiple places in the documentation you say something like "Make sure to wrap all of your components with easyComp - including stateful and stateless ones - before you export them."

Why? If I have a stateless component with no added methods (say, a simple function-based component) am I required to wrap it, or is it just suggested?

Hot Loader Clears Store!

Hello,

I'm using react-hot-loader on my project and I have the store objects declared outside of components.
Every time I do a small change on any of the main or child components the store clears up to default state.
Is this how it is supposed to be .. this is the same as doing a full reload.

Small example with create-react-app

import React from "react";
import { hot } from "react-hot-loader";
import { store, view } from "react-easy-state";

const storage = store({ test: 0 });

class App extends React.Component {
  componentDidMount() {
    storage.test = 1;
  }
  render() {
    console.log("App");
    return <h1>App {storage.test}</h1>;
  }
}

export default hot(module)(view(App));

When I change the header for example from App to App2 the store returns to default.

Thank You!

React Native support

Hi, I just test this library in React Native 0.53.0, and it's work like a charm. If anyone can test on lower version and give some feedback this will be very nice.

Component state not updated when using functions in store

Hi! Thanks for the great react easy state library.

I came across what I believe to be a bug when I decided to store functions in the store.

A reproducible testcase is available at https://github.com/jbq/react-easy-state-function-bug

To start it, type yarn && yarn start.

On the web page, click the Say Hi button, the message below still says Hello, World! instead of the expected Hi, World!.

Now in the source code of src/App.js change const hack_enabled = false to const hack_enabled = true and after app is reloaded click on the Say Hi button: the message is properly updated.

This is because when hack_enabled is turned off, only a function reference changes in the easy state store. And when it's turned on a string value is also changed to force the component update.

Cross-framework state management

The store code is framework independent, which could allow multiple frameworks to use the same stores for state management. Something like the below pseudo code:

import { store, reactView, infernoView } from 'easy-state'

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

@reactView
export class ReactComp {
  render = () => <div>{user.name}</div>
}

@infernoView
export class InfernoComp {
  render = () => <div>{user.name}</div>
}

// the two components come from different frameworks but share the same piece of state

This would make multi-framework projects a lot easier to maintain. We could create a library - code named easy-state - which has a framework independent store implementation and different view implementations for a lot of different frameworks.

Currently I have a lot of projects in mind and won't have time to do this alone. If you have a favorite front-end framework and you are willing to create a view implementation for it, let me know. You can study the React view implementation, if you are interested.

Thanks! 🙂

How to connect two stores

Hi,

I'm trying to connect two stores which live in separated files, but changing the value on one, is not reflected on the other.

You can see an example here:

https://codesandbox.io/s/z6055yr7kp

I'm simulating an ajax request with the setTimeout and, you can see in the codesandbox console, when changing the role from 'user' to 'admin' in the userStore.js, the isLoading function from the store.js is called but the role value is not intercepted.

I'm not sure if this is a bug or just me making a stupid mistake.

ps.
thanks for this project! Is amazing!

The Future: React Easy Stack

Just a little heads-up on my future plans 🙂

This lib is part of my private React stack, which I plan to open-source eventually. Easy State and Easy Params are already open sourced and Easy Router will be the next.

With the release of the router this repo will turn into a monorepo. The npm packages will still be available separately (react-easy-state, react-easy-params and react-easy-router) and also as a complete React framework (react-easy-stack). They will continue to be developed separately, but the source code will get a new home - the react-easy-stack repo - with a unified documentation.

4.1.2 broken with Create React App v2

I am getting this error with create-react-app v2 (react-scripts 2.0.0-next.47d2d941), react 16.2.0 and react-easy-state 4.1.2 when wrapping a Class / Stateful component with view.

image

You can see the issue by cloning this repo: https://github.com/ro-savage/react-easy-state-cra-bug then running npm start. It will crash, then look at the Stateful.js component, remove view and it works fine.

It appears to work fine with CRA v1.

If you think its an issue with create-react-app rather than react-easy-state please cross post to their repo.

Subcomponent rerender

Hello,

just found yesterday this amazing library (i've been following your projects nx-observe and nx-framework for some time).
So i wanted to check it out.

Now i have a small problem. I have to components: "parent" and "child".
The state of parent component looks like this: this.state = { user: { name: "John Doe" } };
I render the child component with user as a prop <Child user={this.state.user} />.

While changing the name in the parent or child component everything is fine this.state.user.name = "foo";. But when i change the complete user object it will propagate it to the child component but wouldn't rerender it this.state.user = { name: "bar" };. The parent component will be rerendered - the child component wouldn't.

Is it possible to do something like this?

Static properties.

I was going through the source and found that the HOC will hide static properties on wrapped components. This is a known issue with HOC as mentioned here.

So, either we should add this thing in the documentation or figure out some robust solution.

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.