{"./":{"url":"./","title":"About Amorphous","keywords":"","body":"About Amorphous Amorphous makes sharing state in react as easy as using setState. Just as this.state is a component's state and can be updated with setState, this.appState is an app's state and can be updated with this.setAppState: class Input extends AppComponent { render() { return ( this.setAppState({ text: e.target.value })} /> ); } } Amorphous is designed to: get your app's state management working as quickly as possible avoid unnecessary pitfalls while doing so Usage Amorphous has two main classes: AppComponent: a class for components that use appState RootAppComponent: a class for the root component of your app To use AppComponent, you must have a RootAppComponent at the root of your app. (For library authors, see using Amorphous in a library.) Both AppComponent and RootAppComponent have access to: this.appState this.setAppState shouldComponentUpdate(nextProps, nextState, appState) componentDidUpdate(nextProps, nextState, snapshot, appState) Full Example: import { AppComponent, RootAppComponent } from 'amorphous'; class Input extends AppComponent { render() { return ( this.setAppState({ text: e.target.value })} /> ); } } class Output extends AppComponent { render() { return ( {'You typed: '} {this.appState.text} ); } } class App extends RootAppComponent { appState = { text: 'hi' }; render() { return ( ); } } "},"getting-started.html":{"url":"getting-started.html","title":"Getting started","keywords":"","body":"Getting started First, install Amorphous by running: npm install amorphous Then, you can import AppComponent and RootAppComponent: import { AppComponent, RootAppComponent } from 'amorphous'; At the root of your application (or subtree), extend RootAppComponent instead of React.Component: class App extends RootAppComponent { // ... } And optionally initialize your appState: class App extends RootAppComponent { constructor(props) { super(props); this.appState = {text: 'hi'}; } } Then, in any component you want to access appState, extend AppComponent instead of React.Component: class Input extends AppComponent { // ... } Inside this component, you can access this.appState and update app state with this.setAppState: class Input extends AppComponent { render() { return this.setAppState({text: e.target.value})} />; } } And you're ready to send shared state to anywhere your app needs it! "},"api.html":{"url":"api.html","title":"API","keywords":"","body":"API RootAppComponent AppComponent this.appState this.setAppState shouldComponentUpdate componentDidUpdate this.appStateContext "},"rootappcomponent.html":{"url":"rootappcomponent.html","title":"RootAppComponent","keywords":"","body":"RootAppComponent RootAppComponent creates a new appState, and should be extended by your app's root component. Any AppComponent must be a descendent of a RootAppComponent (that is, all AppComponents must have a RootAppComponent above them, but not necessarily directly above them, in their component tree). Usage RootAppComponent is a base component, so you should extend from it like you would React.Component. class App extends RootAppComponent { // ... } To initialize appState, you should set appState either as an instance property or in the constructor, as you would with state: class App extends RootAppComponent { state = {}; appState = { someProperty: 0 }; // or: constructor(props) { super(props); this.state = {}; this.appState = { someProperty: 0 }; } } API this.appState Initialize or access appState. this.appState should be initialized in your root component's constructor (or via appState = inside the class body). this.setAppState(update, callback) this.appStateContext shouldComponentUpdate(nextProps, nextState, nextAppState) componentDidUpdate(prevProps, prevState, snapshot, prevAppState) And all React.Component methods "},"appcomponent.html":{"url":"appcomponent.html","title":"AppComponent","keywords":"","body":"AppComponent AppComponent is a replacement for React.Component for any component that needs access to appState. Any AppComponent must be a descendent of a RootAppComponent (that is, all AppComponents must have a RootAppComponent above them, but not necessarily directly above them, in their component tree). Usage AppComponent is a base component, so you should extend from it like you would React.Component. class SomeComponent extends AppComponent { // ... } Your component can access this.appState in render(), as you would access this.state, and can call this.setAppState from within any event handlers, as you would for this.setState. class SomeComponent extends AppComponent { render() { return ( this.setAppState({ buttonClickedCount: this.appState.buttonClickedCount + 1, })} /> ); } } API this.appState Access appState. this.appState should be initialized in your root component's constructor (or via appState = inside the class body). this.setAppState(update, callback) this.appStateContext shouldComponentUpdate(nextProps, nextState, nextAppState) componentDidUpdate(prevProps, prevState, snapshot, prevAppState) And all React.Component methods "},"this.appstate.html":{"url":"this.appstate.html","title":"this.appState","keywords":"","body":"this.appState appState allows all AppComponents (including the RootAppComponent) to share state. It works similarly to this.state, but is shared across all AppComponents. Initializing appState appState is initialized by the RootAppComponent's constructor. By default it is initialized to {}, but you should initialize it to a more reasonable default in your RootAppComponent class: class App extends RootAppComponent { appState = { myToDos: [] }; // or: constructor(props) { super(props); this.appState = { myToDos: [] }; } } Using appState Amorphous provides this.appState in all AppComponents (including your RootAppComponent). NOTE: this.appState is not accessible in the constructor of AppComponents, or in any static methods. This means that in render() or other methods, you can access this.appState to read your app's current state, and display something based on that: class MyToDoList extends AppComponent { render() { return ( {this.appState.myToDos.map((todoItem) => ( ))} ); } } Updating appState AppState can be updated from any AppComponent or RootAppComponent using this.setAppState(). class MyToDoList extends AppComponent { render() { return ( {this.appState.myToDos.map((todoItem) => ( ))} this.setAppState({ myToDos: this.appState.myToDos.concat({ text: '', completed: false, }), })} /> ); } } Read more about setAppState Comparing previous/next appState in lifecycle methods Amorphous provides an additional appState parameter to shouldComponentUpdate and componentDidUpdate for AppComponents and RootAppComponents. This allows components to compare this.appState to previous/next versions of appState. See shouldComponentUpdate and componentDidUpdate for more information. "},"this.setappstate.html":{"url":"this.setappstate.html","title":"this.setAppState","keywords":"","body":"this.setAppState this.setAppState(update, callback) Like this.setState but for app state instead of component state. update may be an object or a function. If update is an object: setAppState will merge update into this.appState If update is a function: update must have the form (prevAppState) => newAppState setAppState will call update with the current appState value, and will merge the returned newAppState value into appState. setAppState is not synchronous, and will call callback after it has completed merging update into appState. "},"shouldcomponentupdate.html":{"url":"shouldcomponentupdate.html","title":"shouldComponentUpdate","keywords":"","body":"shouldComponentUpdate Amorphous provides this.appState and this.setAppState during and after your component's first render. They are not accessible in the constructor. Additionally, Amorphous provides an appState parameter for the following React lifecycle methods: shouldComponentUpdate(nextProps, nextState, nextAppState) componentDidUpdate(prevProps, prevState, snapshot, prevAppState) You may use either of these methods to monitor changes to appState and update your AppComponent properly, like you would for this.state. Amorphous AppComponents and RootAppComponents provide a third parameter to shouldComponentUpdate: nextAppState, which indicates the next value of appState, so that components may avoid rendering if none of their dependent props/state/appState have changed. See lifecycle methods for more details and examples. "},"componentdidupdate.html":{"url":"componentdidupdate.html","title":"componentDidUpdate","keywords":"","body":"componentDidUpdate Amorphous provides this.appState and this.setAppState during and after your component's first render. They are not accessible in the constructor. Additionally, Amorphous provides an appState parameter for the following React lifecycle methods: shouldComponentUpdate(nextProps, nextState, nextAppState) componentDidUpdate(prevProps, prevState, snapshot, prevAppState) You may use either of these methods to monitor changes to appState and update your AppComponent properly, like you would for this.state. Amorphous AppComponents and RootAppComponents provide a fourth parameter to componentDidUpdate: prevAppState, which holds the value of appState before the most recent render, and may be useful for comparing with the new this.appState value to perform non-react updates after the component has rendered. See lifecycle methods for more details and examples. Note: snapshot is the return value of getSnapshotBeforeUpdate(), or undefined if no getSnapshotBeforeUpdate() is specified. "},"getderivedappstate.html":{"url":"getderivedappstate.html","title":"getDerivedAppState","keywords":"","body":"getDerivedAppState static getDerivedAppState(appState) Similar to getDerivedStateFromProps, Amorphous supports a static getDerivedAppState method on the RootAppComponent only. This function may be used to trigger additional modifications of appState when appState is modified, which can be useful for caching expensive calculations or time-unique values. Example: "},"using-amorphous-in-a-library.html":{"url":"using-amorphous-in-a-library.html","title":"Using Amorphous in a Library","keywords":"","body":"Using Amorphous in a Library If you are a library author using Amorphous, it is important to make sure your library's appState does not conflict with the client's appState. Amorphous uses React context to control which components have access to which appStates. To make a new context for your library, use: import { createAppStateContext } from 'amorphous'; const MyAppStateContext = createAppStateContext(); Then, to specify that your components use MyAppStateContext instead of the default appState context, set the appStateContext property on those components: class MyApp extends RootAppComponent { appStateContext = MyAppStateContext; // ... } class MyComponent extends AppComponent { appStateContext = MyAppStateContext; // ... } To make this less reduntant, I suggest making your own RootAppComponent and AppComponent classes for your library with extension: Making Amorphous classes for your library import { AppComponent, RootAppComponent, createAppStateContext } from 'amorphous'; const MyAppStateContext = createAppStateContext(); export class MyAppComponent extends AppComponent { appStateContext = MyAppStateContext; } export class MyRootAppComponent extends RootAppComponent { appStateContext = MyAppStateContext; } Then everywhere you would use AppComponent or RootAppComponent, you can instead use MyAppComponent or MyRootAppComponent from that file's exports. "},"using-amorphous-with-flow.html":{"url":"using-amorphous-with-flow.html","title":"Using Amorphous with Flow","keywords":"","body":"Using Amorphous with Flow Amorphous has full support for flow types. The relevant type information for RootAppComponent and AppComponent is: class RootAppComponent extends React.Component { } class AppComponent extends React.Component { } To use these types, you can specify Props, State, and AppState types, and use these in your component declarations. We recommend creating your AppState type in its own file, which can be included from all your components. import { RootAppComponent } from 'amorphous'; import type { AppState } from './my-app-state-type.js'; type Props = { mode: string, }; type State = { }; class App extends RootAppComponent { appState: AppState = { // ... }; render() { // ... } } "}}