JSPM

react-stately

0.3.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 969503
  • Score
    100M100P100Q182875F
  • License Apache-2.0

A library for simple management of shared React state

Package Exports

  • react-stately

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (react-stately) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

react-stately

A library for simple management of shared React state

Introduction

Stately is a simple, easy-to-use state management library for React relying on the render props pattern. It has components for managing both local state and global state in a React component tree. When managing global state, it scopes state access and mutations under a Ramda lens. This helps you be declarative about which parts of the global state your components rely upon.

Resources

Managing Local State

You can manage local state in Stately using the Stately component. First, set the initial state with a prop on the Stately component, which is equivalent to setting the state in the constructor of a React stateful class component. Then, provide the Stately component with a render prop, which gives you access to the local state and the setState method, which work exactly the same as this.state and this.setState in a React stateful class component.

<Stately
  initialState={{ isAsleep: true }}
  render={(state, setState) => (
    <button onClick={() => setState({ isAsleep: false })}>
      {state.isAsleep ? 'zzz... (click to wake me)' : 'good morning'}
    </button>
  )}
/>

This example renders a button that initially renders a sleeping message. When clicked, the button displays a "good morning" message. To manage the state of whether the button is "asleep," we use an isAsleep boolean value, which starts with an initial value of true in the initialState. When the user clicks the button, we use the setState method to update the isAsleep value to false. Since we use this state to control which message is displayed inside the button, clicking the button will change the displayed message.

Note that you may provide a function to setState to base it off the previous state, which works exactly as it does in React. If you needed to, you could provide a callback as the second argument to setState as well, which is also the same as in React. Generally, you should assume any setState in Stately works similarly to React's this.setState method. There is one caveat to this when managing global state, which is explained below.

Managing Global State

Stately also supports managing global state. This uses the Provider pattern to share a Stately component with the entire React tree. You must provide the StatelyProvider with an initial state, which will be passed down to the Stately component it manages. Then, anywhere in the tree below the StatelyProvider, you can use a ConnectedStately component to access the global state. This takes a render prop which is similar to the Stately component's render prop. However, when using ConnectedStately, you must provide a Ramda lens to scope your access to the global state. This is to help you declare which part of the global state this specific ConnectedStately is trying to manage. See the Resources section of this document for some links to help you learn about Ramda lenses, or check out the Ramda documentation.

<StatelyProvider
  initialState={{ auth: { isLoggedIn: false }, counter: { value: 0 } }}
>
  <ConnectedStately
    lens={R.lensProp('counter')}
    render={(state, setState) => (
      <button
        onClick={() => {
          setState(({ value: oldValue }) => ({ value: oldValue + 1 }))
        }}
      >
        Increment the value
      </button>
    )}
  />
  <ConnectedStately
    lens={R.lensProp('authentication')}
    render={(state, setState) => (
      <div>
        <button
          onClick={() => {
            setState(({ isLoggedIn: wasLoggedIn }) => ({
              isLoggedIn: !wasLoggedIn
            }))
          }}
        >
          {state.isLoggedIn ? 'Log out' : 'Log in'}
        </button>
        <ConnectedStately
          lens={R.lensProp('counter')}
          render={state => (
            <span>We can access the counter here too: {state.value}</span>
          )}
        />
      </div>
    )}
  />
</StatelyProvider>

In the above example, we have a global state with some authentication information and a counter value. It works very similarly to the local state example, except we provide the initial state in the provider and access it using the ConnectedStately component. We have a counter button at the top which accesses the global state under the counter key to increment the value when the button is pressed. Below that, there's an authentication button which is scoped under the global auth key. This allows you to click to log in and out, changing the text of the button. But also, inside the component managing the authentication button, we also display the value of the counter using a nested ConnectedStately component.

If you need to access multiple parts of the global state, you should use nested ConnectedStately components with different Ramda lenses, one for each scope in the global state to which you need access. Note that we do this above to access the counter value inside the authentication section. If you find yourself doing this a lot, maybe it's important to re-evaluate the structure of the global state to place similar information together. This should lead to cleaner global state management code, which is one of the goals of Stately.

Notice how using lenses allows us to separate the concerns of authentication and the counter. This helps you to build global state management solutions that play together nicely. There's no guessing about which part of the state each piece of the application manages. Even when we do things like accessing various parts of the state in the same piece of the application, we still get the same declarative nature. This is one of the major strong points of using Stately over a normal Javascript global.

License

Copyright 2018 Christian Howe

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.