Options
All
  • Public
  • Public/Protected
  • All
Menu

Package muster-react

Muster-React

Introduction

Muster-React is a library that helps using Muster in an application written in React.

Installation

npm install --save @dws/muster-react

Usage

Muster-React exposes a container function which is used for creating a wrapper for a React component. This wrapper component is responsible for making queries to Muster, handling responses and passing them as props to the wrapped component. The wrapper component assumes the existence of a muster property on a React context. It can be set with the help of a Provider component. The library exports a modified version of a muster helper. By default, when using muster from @dws/muster it creates an application with all core muster graph nodes. This custom version of muster helper additionally includes all muster-react graph nodes.

Setting up Muster Provider

import * as React from 'react';
import muster, { Provider } from '@dws/muster-react';

// Create a muster app const app = muster({ name: 'Bob', });

function Application() { return ( <Provider muster={app}> {/* Your application goes here */} </Provider> ); }

This example shows how to create a Muster application that has a single branch name. The Application component is responsible for storing that application on the React context so that any child component has access to it.

Creating connected components

import * as React from 'react';
import { container } from '@dws/muster-react';

function MyComponent({ name }) { return <h1>{name}</h1>; }

const MyConnectedComponent = container({ graph: { name: 'Bob', }, props: { name: true, }, })(MyComponent);

// To render this component simply type <MyConnectedComponent /> // No props are needed as they'll be injected by Muster-React

This example shows how to create a very basic Muster-React component. We first start by creating a pure React component that takes one prop name. Next we create a connected component out of it. When creating a Muster application we do this by defining a Muster graph with nodes and relationships between them. Muster-React connects that global graph through the Provider discussed in the previous example. The global graph contains the state of the application and it is shared between all of the connected components. Additionally, each component has its own, local graph. This graph is unique to every instance of a given component - one component does not have access to another component's local graph. In this example, the configuration of the connected component is split into two parts:

  • graph - Defines the local graph - here you can use any graph nodes, just like in the pure muster. Refs defined in this graph are addressed against the root of the local graph. In order to make a reference to a global graph you have to define it as: ref(global('nested', 'global', 'path'))
  • props - Nodes to retrieve from the local graph. The nodes can be retrieved as:
    • getter - Gets the value of a graph node
    • setter - Gets a function that can be used to set the value of the settable node
    • caller - Gets a function that can be used to call an action
    • list - Gets a list of items

In this example we used a short-hand getter notation - name: true. This means we simply want to get the value of the name node. Internally Muster-React prepares a query that looks like this:

import { key, query, root } from '@dws/muster';

const myConnectedComponentQuery = query(root(), { name: key('name'), });

The connected component runs that query against the local graph and subscribes to the result when its componentWillMount method get called by React. The subscription is closed when the componentWillUnmount method gets called by React.

Referencing global graph

import * as React from 'react';
import muster, { container, global, Provider, ref } from '@dws/muster-react';

function User({ name }) { return <h1>{name}</h1> }

const ConnectedUser = container({ graph: { name: ref(global('user', 'name')), }, props: { name: true, }, })(User);

const app = muster({ user: { name: 'Bob', }, });

function Application() { return ( <Provider muster={app}> <ConnectedUser /> </Provider> ); }

This example shows how to make references to the global muster graph.

Using setter prop type

import * as React from 'react';
import { container, propTypes, types, variable } from '@dws/muster-react';

function NewsletterSettings({ sendNewsletter, setSendNewsletter }) { return ( <button onClick={() => setSendNewsletter(!sendNewsletter)}> {sendNewsletter ? 'Stop sending newsletter' : 'Subscribe to newsletter'} </button> ); }

const ConnectedNewsletterSettings = container({ graph: { sendNewsletter: variable(false), }, props: { sendNewsletter: types.bool, setSendNewsletter: propTypes.setter('sendNewsletter', types.bool), }, })(NewsletterSettings);

This example shows how to declare setter props and how to use them. This example also introduces the concept of typed props. In previous example we've been defining props as propName: true which is a short-hand of propName: types.any. In this example we defined the type of the prop explicitly: sendNewsletter: types.bool. This will inform Muster to validate the type of the property as bool. Next we're defining a setSendNewsletter property, which is a setter of a sendNewsletter node and that it should be validated as a setter of a boolean values.

In this example we're completely ignoring the return value of the setSendNewsletter setter function but it's important to remember that it is returning a Promise that resolves to a value that was set.

Using caller prop type

import * as React from 'react';
import { action, container, propTypes } from '@dws/muster-react';

function Something({ getGreeting }) { async function onClick() { const greeting = await getGreeting('Bob'); console.log(greeting); // Hello, Bob } return ( <button onClick={onClick}>Log greeting</button> ); }

const ConnectedSomething = container({ graph: { getGreeting: action((name) => Hello, <span class="hljs-subst">${name}</span>), }, props: { getGreeting: propTypes.caller(), }, })(Something);

This example shows how to declare an action, get a caller for it and call it. It is similar to the previous example with setter in a way that the getGreeting caller function returns a promise, just like the setter function in a previous example.

Typed getter prop type

import * as React from 'react';
import { container, types } from '@dws/muster-react';

function MyComponent({ name }) { // Display the name return null; }

const MyConnectedComponent = container({ graph: { name: 'Bob', }, props: { name: types.string, }, })(MyComponent);

This example shows how to use Muster types to declare a type of a prop that should be injected to the component.

Named getter prop type

import * as React from 'react';
import { container, propTypes, types } from '@dws/muster-react';

function MyComponent({ myName }) { // Display the name return null; }

const MyConnectedComponent = container({ graph: { firstName: 'Bob', }, props: { myName: propTypes.getter('firstName', types.string), }, })(MyComponent);

This example shows how to use the getter prop type to retrieve a node with a different name than the name used for the prop.

Retrieving nested data

import * as React from 'react';
import { container } from '@dws/muster-react';

function MyComponent({ user }) { // Display the user return null; }

const MyConnectedComponent = container({ graph: { user: { firstName: 'Bob', lastName: 'Doe', address: { line1: '1141 Losbi Lane', postCode: 'A0Y 6D3', }, }, }, props: { user: { firstName: true, lastName: true, address: { line1: true, }, }, }, })(MyComponent);

This example shows how to request a nested data from local graph. By now you've noticed that the shape of the props must match the shape of the graph. You might have also noticed that the address in the local graph defines a postCode node but the props are not requesting it. This shows that you don't have to load everything from your local graph to the component props.

Retrieving nested data from global graph

import * as React from 'react';
import muster, { container, global, Provider, ref } from '@dws/muster-react';

const app = muster({ currentUser: { firstName: 'Bob', lastName: 'Doe', address: { line1: '1141 Losbi Lane', postCode: 'A0Y 6D3', }, }, });

function MyComponent({ firstName, lastName, address }) { // Display the user return null; }

const MyConnectedComponent = container({ graph: ref(global('currentUser')), props: { firstName: true, lastName: true, address: { line1: true, }, }, })(MyComponent);

function Application() { return ( <Provider muster={app}> <MyConnectedComponent /> </Provider> ); }

In the example Referencing global graph we showed that nodes from the local graph can reference parts of the global graph. This example extends that concept by showing that the entire local graph can point to a specific part of a global graph. This means that every prop must match branch names from the currentUser in the global graph.

Using list prop type for value-based collection

import * as React from 'react';
import { container, propTypes } from '@dws/muster-react';

function MyComponent({ numbers }) { // Display the numbers. // In this example numbers = [1, 2, 3, 4] return null; }

const MyConnectedComponent = container({ graph: { numbers: [1, 2, 3, 4], }, props: { numbers: propTypes.list(), }, })(MyComponent);

This example shows how to use the list prop type to retrieve items from a collection.

Using list prop type for branch-based collection

import * as React from 'react';
import { container, propTypes } from '@dws/muster-react';

function MyComponent({ friends }) { // Display the list of friends // In this example friends = [ // { firstName: 'Sylvia', lastName: 'Garcia' }, // { firstName: 'Carl', lastName: 'Francis' }, // { firstName: 'Arthur', lastName: 'Kennedy' }, // ] return null; }

const MyConnectedComponent = container({ graph: { friends: [ { firstName: 'Sylvia', lastName: 'Garcia', age: 48 }, { firstName: 'Carl', lastName: 'Francis', age: 63 }, { firstName: 'Arthur', lastName: 'Kennedy', age: 28 }, ], }, props: { friends: propTypes.list({ firstName: true, lastName: true, }), }, })(MyComponent);

This example shows how to use the list prop type to retrieve items with specific properties from a collection. In this case we omitted the age property as it wasn't necessary for our component.

Loading asynchronous data

In Muster there's no difference between loading synchronously available data and asynchronous. Queries run against Muster graph are waiting for the entire data-set to be loaded before returning it to the subscribers.

import * as React from 'react';
import { container, fromPromise } '@dws/muster-react';

function MyComponent(props) { console.log('Rendering the component: ', props); return null; }

const MyConnectedComponent = container({ graph: { async: fromPromise(() => Promise.resolve('value')), sync: 'value', }, props: { async: true, sync: true, }, })(MyComponent);

// Console output (when rendered): // Rendering the component: { async: 'value', sync: 'value' }

This example shows that the rendering happens only when all of the data is loaded. This prevents inconsistent UI states and ensures the minimum amount of renders.

Deferring asynchronous data

There are sometimes moments when you would like to show a loading spinner when some data is loading as it might take longer time to retrieve it from the server. Muster-React introduces two prop types doing just that: defer and isLoading.

The defer prop can be applied to any getter and list prop, and it instructs Muster to load the given node asynchronously. When the node does not resolve immediately for the first time it will return a fallback value: null. However, when the node was resolved and goes to the pending state again this prop will return a previous value of this node as a fallback.

The isLoading prop is a meta-property which takes a name of a different prop from the same branch (it must be a prop wrapped in a defer) and monitors the pending state of it.

import * as React from 'react';
import { container, fromPromise, propTypes } '@dws/muster-react';

function MyComponent(props) { console.log('Rendering the component: ', props); return null; }

const MyConnectedComponent = container({ graph: { async: fromPromise(() => Promise.resolve('value')), sync: 'value', }, props: { async: propTypes.defer(true), isLoadingAsync: propTypes.isLoading('async'), // It isn't necessary for the defer to work as described sync: true, // isLoadingSync: propTypes.isLoading('sync'), // ERROR, sync is not deferred! }, })(MyComponent);

// Console output (when rendered): // Rendering the component: { async: null, isLoadingAsync: true, sync: 'value' } // Rendering the component: { async: 'value', isLoadingAsync: false, sync: 'value' }

This example shows how to defer loading certain parts of the graph. One thing to remember is that for this to work correctly, every asynchronous prop must be wrapped in defer. This is due to the fact, that Muster normally waits for all data to be loaded before returning it to subscriber. The defer prop is notifying Muster that a particular graph node is not crucial for the application to work and the query doesn't have to wait for it to resolve. When some other nodes in the query share the same async behaviour but aren't wrapped in defer they will be blocking the query from resolving. The following example shows how that might happen:

import * as React from 'react';
import { container, fromPromise, propTypes } '@dws/muster-react';

function MyComponent(props) { console.log('Rendering the component: ', props); return null; }

const MyConnectedComponent = container({ graph: { async1: fromPromise(() => Promise.resolve('value 1')), async2: fromPromise(() => Promise.resolve('value 2')), sync: 'value', }, props: { async1: propTypes.defer(true), async2: true, sync: true, }, })(MyComponent);

// Console output (when rendered): // Rendering the component: { async1: 'value 1', async2: 'value 2', sync: 'value' }

The component is rendered only once, because the async2 prop is not marked as deferred.

Handling loading state

So far we've covered how to handle loading non-crucial data. It's not always possible to render a component without certain points of data. For these cases you can use a special property of container - renderLoading. It takes a function which will be called whenever a component goes into a loading state - data is pending but not marked as deferred. The function takes one parameter: last props, and is expected to return a JSX Element to render. You can use this function to render for example a loading spinner.

import * as React from 'react';
import { container, fromPromise } '@dws/muster-react';

function MyComponent(props) { console.log('Rendering the component: ', props); return null; }

const MyConnectedComponent = container({ graph: { async: fromPromise(() => Promise.resolve('value')), sync: 'value', }, props: { async: true, sync: true, }, renderLoading: (props) => { console.log('Rendering a loading spinner'); return null; }, })(MyComponent);

// Console output (when rendered): // Rendering a loading spinner // Rendering the component: { async: 'value', sync: 'value' }

Handling errors

Error handling is as very important part of application development. Sometimes it's the network problem, a simple developer mistake, or user trying to do something incorrectly. Good applications should be able to recover from these kinds of issues. Muster and Muster-React enable a few layers of error handling:

  • Network-layer error handling by means of transformResponseMiddleware and handleErrors helper
  • Node-level error handling with the IfErrorNode
  • container - renderError function.

The first two methods of error handling are covered in Muster documentation. This example will focus only on the last one - renderError.

import * as React from 'react';
import { container, computed } '@dws/muster-react';

function MyComponent(props) { console.log('Rendering the component: ', props); return null; }

const MyConnectedComponent = container({ graph: { name: computed([], () => { throw new Error('Some unexpected error'); }), }, props: { name: true, }, renderError: (errors, props) => { console.log('An error has occurred: ', errors); return null; }, })(MyComponent);

// Console output (when rendered): // An error has occurred: [ // { $type: 'error', error: new Error('Some unexpected error'), path: ['name'] }, // ]

This example shows how to use the renderError method to access the array of errors.

Accessing react props from the local graph

As mentioned at the beginning of this document, the connected component does not require any react props to run correctly. That doesn't mean it can't have any props. Any additional props set on a connected component can be accessed from the local graph with the help of a PropNode. This example shows how to access such props:

import * as React from 'react';
import { container, computed, prop } from '@dws/muster-react';

function MyComponent({ greeting }) { console.log('Greeting: ', greeting); return null; }

const MyConnectedComponent = container({ graph: { greeting: computed([prop('name')], (name) => Hello, <span class="hljs-subst">${name}</span>), }, props: { greeting: true, }, })(MyComponent);

// Somewhere in another part of the application: <MyConnectedComponent name="Bob" />

// Console output (when rendered): // Greeting: Hello, Bob

Index

Classes

Interfaces

Type aliases

Variables

Functions

Object literals

Type aliases

CallerArgumentMatcher

CallerArgumentMatcher: Matcher<Array<any>, CallerMatcher<N, A>>

CallerMatcher

CallerMatcher: Matcher<Function, CallerOptions<N, A>>

CatchErrorMatcher

CatchErrorMatcher: Matcher<T, CatchErrorMatcherOptions<T, O, M>>

ContainerComponentFactory

ContainerComponentFactory: function

Type declaration

DeferMatcher

DeferMatcher: Matcher<T, DeferMatcherOptions<T, O, M>>

DisposeListener

DisposeListener: function

Type declaration

    • (): void
    • Returns void

GetterMatcher

GetterMatcher: Matcher<TT, GetterOptions<N, T>>

InjectedMatcher

InjectedMatcher: Matcher<any, InjectedOptions>

InjectedProps

InjectedProps: object

Type declaration

IsLoadingMatcher

IsLoadingMatcher: Matcher<any, string>

ListMatcher

ListMatcher: Matcher<Array<F>, ListOptions<N, I>>

MusterReactOperationDefinition

MusterReactScenarioDefinition

MusterReactScenarioInput

MusterReactScenarioInput: undefined | NodeDefinition<any, any, any, object, any, StaticNodeType<any, any, any> | StatelessNodeType<any, any, any, string, GraphOperation<string, object, object, OperationType<string, object, object>>> | StatefulNodeType<any, any, any, object, any, string, GraphOperation<string, object, object, OperationType<string, object, object>>>> | function

Props

Props: object

Type declaration

PropsInjector

PropsInjector: function

Type declaration

    • (props: any, injectedProps: any): any
    • Parameters

      • props: any
      • injectedProps: any

      Returns any

ResolvedProps

ResolvedProps: object

Type declaration

ScopeTransformer

ScopeTransformer: function

Type declaration

    • (scope: any, props: any, metadata: any): any
    • Parameters

      • scope: any
      • props: any
      • metadata: any

      Returns any

SetterMatcher

SetterMatcher: Matcher<Function, SetterOptions<N, T>>

SetterValueMatcher

SetterValueMatcher: Matcher<any, SetterMatcher<N, T>>

TreeFields

TreeFields: object

Type declaration

TreeMatcher

TreeMatcher: Matcher<T, TreeFields<T>>

TreeProps

TreeProps: object

Type declaration

TreeValidator

TreeValidator: function

Type declaration

    • (props: any): Array<Error>
    • Parameters

      • props: any

      Returns Array<Error>

Variables

Const AsyncValueNodeType

AsyncValueNodeType: StatefulNodeType<"async-value", AsyncValueNodeProperties, AsyncValueNodeState> = createNodeType<'async-value', AsyncValueNodeProperties, AsyncValueNodeState>('async-value', {state: {currentValue: graphTypes.nodeDefinition,},shape: {value: types.any,},getInitialState(): AsyncValueNodeState {return {currentValue: pending(),};},operations: {evaluate: {run(node: AsyncValueNode,options: never,dependencies: Array<never>,context: Array<never>,state: AsyncValueNodeState,): NodeDefinition {return state.currentValue;},onSubscribe(this: NodeExecutionContext<AsyncValueNodeState, AsyncValueNodeData>,node: AsyncValueNode,): void {setTimeout(() => {this.setState({currentValue: toValue(node.definition.properties.value),});});},},},})

Const GLOBAL_ROOT_NODE

GLOBAL_ROOT_NODE: "$$container:globalRoot:node" = "$$container:globalRoot:node"

Const GlobalRootNodeType

GlobalRootNodeType: StatelessNodeType<"global-root", GlobalRootNodeProperties> = createNodeType<'global-root', GlobalRootNodeProperties>('global-root', {shape: {},operations: {evaluate: {run(node: GlobalRootNode): NodeDefinition | GraphNode {if (!(GLOBAL_ROOT_NODE in node.context.values)) {return error('Global root node is not available.');}return node.context.values[GLOBAL_ROOT_NODE];},},},})

The implementation of the GlobalRootNode. See the GlobalRootNode documentation to learn more.

Const INJECTED_CONTEXT_NAME

INJECTED_CONTEXT_NAME: "$$injected" = "$$injected"

Const INJECTED_PROPS_NAME

INJECTED_PROPS_NAME: "$inject" = "$inject"

Const InjectedNodeType

InjectedNodeType: StatefulNodeType<"injected", InjectedNodeProperties, InjectedNodeState> = createNodeType<'injected', InjectedNodeProperties, InjectedNodeState>('injected', {state: {currentValue: graphTypes.nodeDefinition,},shape: {path: types.arrayOf(types.string),},getInitialState(): InjectedNodeState {return {currentValue: pending(),};},operations: {evaluate: {run(node: InjectedNode,options: never,dependencies: Array<never>,context: Array<never>,state: InjectedNodeState,): NodeDefinition {return state.currentValue;},onSubscribe(this: NodeExecutionContext<InjectedNodeState, InjectedNodeData>,node: InjectedNode,): void {// Verify the pathconst { path } = node.definition.properties;// Check if the right context value is setif (!(INJECTED_CONTEXT_NAME in node.context.values)) {this.setState({currentValue: error('Injected node can only be used within a container'),});return;}// Verify the injected context valueconst injectedNode = node.context.values[INJECTED_CONTEXT_NAME];if (!ValueNodeType.is(injectedNode)) {this.setState({currentValue: error(getInvalidTypeError('Invalid type of requirements stream supplied with the context.',{expected: ['value(Observable<any>)'],received: injectedNode,},),),});return;}// Verify the injected props streamconst injectedPropsStream = (injectedNode as ValueNode<ObservableLike<any>>).definition.properties.value;if (!isObservable(injectedPropsStream)) {this.setState({currentValue: error(getInvalidTypeError('Requirements context value has invalid type.', {expected: ['Observable<any>'],received: injectedPropsStream,}),),});return;}const { subscription: previousSubscription } = this.getData();this.setData({subscription: injectedPropsStream.subscribe((v) => {this.setState({currentValue: toValue(lodashGet(v, path)),});}),});previousSubscription && previousSubscription.unsubscribe();},onUnsubscribe(this: NodeExecutionContext<InjectedNodeState, InjectedNodeData>): void {const { subscription } = this.getData();subscription && subscription.unsubscribe();},},},})

The implementation of the injected node. See the injected documentation to learn more.

Const PENDING_TOKEN

PENDING_TOKEN: unique symbol = Symbol('pending')

Const PropNodeType

PropNodeType: StatefulNodeType<"prop", PropNodeProperties, PropNodeState> = createNodeType<'prop', PropNodeProperties, PropNodeState>('prop', {state: {currentValue: graphTypes.nodeDefinition,},shape: {name: types.string,},getInitialState(): PropNodeState {return {currentValue: pending(),};},operations: {evaluate: {run(node: PropNode,options: never,dependencies: Array<never>,context: Array<never>,state: PropNodeState,): NodeDefinition {return state.currentValue;},onSubscribe(this: NodeExecutionContext<PropNodeState, PropNodeData>, node: PropNode): void {// Check if the right context value is setif (!(REACT_PROP_CONTEXT_NAME in node.context.values)) {this.setState({currentValue: error('Prop node can only be used within a container'),});return;}// Verify the props context valueconst propsNode = node.context.values[REACT_PROP_CONTEXT_NAME];if (!ValueNodeType.is(propsNode)) {this.setState({currentValue: error(getInvalidTypeError('Invalid type of props stream supplied with the context.', {expected: ['value(ObservableLike<any>)'],received: propsNode,}),),});return;}// Verify the props streamconst propsStream = (propsNode as ValueNode<ObservableLike<any>>).definition.properties.value;if (!isObservable(propsStream)) {this.setState({currentValue: error(getInvalidTypeError('React props context value has invalid type.', {expected: ['Observable<any>'],received: propsStream,}),),});return;}const { subscription: previousSubscription } = this.getData();this.setData({subscription: propsStream.subscribe((props) => {this.setState({currentValue: props? toValue(props[node.definition.properties.name]): value(undefined),});}),});previousSubscription && previousSubscription.unsubscribe();},onUnsubscribe(this: NodeExecutionContext<PropNodeState, PropNodeData>): void {const { subscription } = this.getData();subscription && subscription.unsubscribe();},},},})

The implementation of the prop node. See the prop documentation to learn more.

Const REACT_PROP_CONTEXT_NAME

REACT_PROP_CONTEXT_NAME: "$$props" = "$$props"

Const hoistNonReactStatics

hoistNonReactStatics: any = require('hoist-non-react-statics')

Const operation

operation: (Anonymous function) & object = Object.assign((definition: MusterReactOperation): MusterReactOperation => definition,{only(definition: MusterReactOperation): MusterReactOperation {return { ...definition, only: true };},skip(definition: MusterReactOperation): MusterReactOperation {return { ...definition, skip: true };},},)

Const showCreateContainerDeprecationWarning

showCreateContainerDeprecationWarning: function = deprecated({old: 'createContainer',new: 'container',})

Type declaration

    • (): void
    • Returns void

Const showDataDeprecationWarning

showDataDeprecationWarning: function = deprecated({ old: 'data', new: 'graph' })

Type declaration

    • (): void
    • Returns void

Const showGlobalArrayDeprecationWarning

showGlobalArrayDeprecationWarning: function = deprecated({ old: 'global([...])', new: 'global(...)' })

Type declaration

    • (): void
    • Returns void

Functions

asyncValue

buildMatcherValidator

  • buildMatcherValidator(matcher: Matcher<any>, path: Array<string>): TreeValidator

buildPropsInjector

buildPropsInjectorForPath

buildQuery

  • buildQuery<T>(disposeEmitter: DisposeEmitter, treeMatcher: TreeMatcher<T>, queryRoot?: NodeDefinition): NodeDefinition | undefined

buildSettersAndCallersQuery

  • buildSettersAndCallersQuery<T>(disposeEmitter: DisposeEmitter, treeMatcher: TreeMatcher<T>, queryRoot?: NodeDefinition): NodeDefinition | undefined

buildTopLevelPropsInjector

buildTreeValidator

caller

  • Creates a matcher used as part of the props section of the container and simpleContainer. This matcher informs muster-react that a given property should be loaded from the graph as a function. The returned function is an asynchronous function that returns a promise when called. Calling it will cause a matching callable node in the graph to be called with the help of a call() node.

    In order for the function returned from the graph to work correctly the node in your graph must support call operation. Examples of nodes that support call operation: action, [[fn]], placeholder. If the node targeted by the caller does not support the call operation then calling the returned function will result in the promise being rejected with an error.

    example

    Call an action from the graph

    import { action, container, propTypes } from '@dws/muster-react';
    
    const myContainer = container({
      graph: {
        myAction: action(() => {
          console.log('myAction was called');
        }),
      },
      props: {
        myAction: propTypes.caller(),
      },
    });
    
    const MyComponent = myContainer(({ myAction }) => (
      <button onClick={myAction}>Click me</button>
    ));
    
    // Console output (after clicking the button):
    // myAction was called

    This example shows how to use the caller prop type to be able to call an action defined in the local container graph. The code above ignores the fact that the myAction is an asynchronous function that returns a promise, and just calls it every time the button is clicked. In most cases this is how a muster action should be called from your components.

    example

    Call an action from the graph, and read the return value

    import { action, container, propTypes } from '@dws/muster-react';
    
    const myContainer = container({
      graph: {
        myAction: action(() => {
          console.log('myAction was called');
          return 'some value from myAction';
        }),
      },
      props: {
        myAction: propTypes.caller(),
      },
    });
    
    const MyComponent = myContainer(({ myAction }) => {
      async function onButtonClick() {
        const result = await myAction();
        console.log('Result: ', result);
      }
      return (
        <button onClick={onButtonClick}>Click me</button>
      );
    });
    
    // Console output (after clicking the button):
    // myAction was called
    // Result: some value from myAction

    This example shows how to utilise the asynchronous nature of the functions returned from the graph.

    example

    Call an action with arguments

    import { action, container, propTypes } from '@dws/muster-react';
    
    const myContainer = container({
      graph: {
        myAction: action((name) => {
          console.log('myAction was called with name: ', name);
          return `Hello, ${name}`;
        }),
      },
      props: {
        myAction: propTypes.caller(),
      },
    });
    
    const MyComponent = myContainer(({ myAction }) => {
      async function onButtonClick() {
        const result = await myAction('Bob');
        console.log('Result: ', result);
      }
      return (
        <button onClick={onButtonClick}>Click me</button>
      );
    });
    
    // Console output (after clicking the button):
    // myAction was called with name: Bob
    // Result: Hello, Bob

    This example shows how to pass an argument to an action. There is no limit to the number of arguments that can be passed to the action, just like in a normal JavaScript function.

    example

    Create a caller with a different name than the graph action

    import { action, container, propTypes } from '@dws/muster-react';
    
    const myContainer = container({
      graph: {
        someActionNameYouDontLike: action(() => {
          console.log('someActionNameYouDontLike was called');
        }),
      },
      props: {
        myAction: propTypes.caller('someActionNameYouDontLike'),
      },
    });
    
    const MyComponent = myContainer(({ myAction }) => (
      <button onClick={myAction}>Click me</button>
    ));
    
    // Console output (after clicking the button):
    // someActionNameYouDontLike was called

    The caller prop type also enables aliasing actions. In this example the action in the graph was named someActionNameYouDontLike, which for some reason we don't find to our taste when defining props. With the help of caller you can define the name of the prop to be completely different than the name of the action defined in the graph.

    example

    Validate types of arguments

    import { action, container, propTypes, types } from '@dws/muster-react';
    
    const myContainer = container({
      graph: {
        myAction: action((name) => {
          console.log('myAction was called with name: ', name);
          return `Hello, ${name}`;
        }),
      },
      props: {
        myAction: propTypes.caller([types.string]),
      },
    });
    
    const MyComponent = myContainer(({ myAction }) => {
      async function onButtonClick() {
        console.log('Calling `myAction` with a string argument');
        try {
          const result = await myAction('Bob');
          console.log('Result: ', result);
        } catch (ex) {
          console.log('Didn\'t work');
        }
    
        console.log('Calling `myAction` with a number argument');
        try {
          const result = await myAction(123);
          console.log('Result: ', result);
        } catch (ex) {
          console.log('Didn\'t work');
        }
      }
      return (
        <button onClick={onButtonClick}>Click me</button>
      );
    });
    
    // Console output (after clicking the button):
    // Calling `myAction` with a string argument
    // myAction was called with name: Bob
    // Result: Hello, Bob
    // Calling `myAction` with a number argument
    // Didn't work

    This example shows how to add validation to the type of arguments accepted by the callable function returned from the graph. In the first try block of the onButtonClick we're calling the myAction with a string 'Bob', which returns a correct value. In the next block we try our luck by passing a numeric value 123, but muster-react catches us before that argument ends up in the body of the myAction.

    Returns CallerMatcher<undefined, undefined>

  • Parameters

    • name: string

    Returns CallerMatcher<string, undefined>

  • Type parameters

    • PT

    • PP

    • P: Matcher<PT, PP>

    • A: Array<P>

    Parameters

    • args: A

    Returns CallerMatcher<undefined, A>

  • Type parameters

    • PT

    • PP

    • P: Matcher<PT, PP>

    • A: Array<P>

    Parameters

    • name: string
    • args: A

    Returns CallerMatcher<string, A>

callerArguments

catchError

  • Creates a matcher used as part of the props section of the container and simpleContainer. This matcher informs muster-react that a given property can sometimes resolve to an error node, and that Muster should replace that error with a fallback specified by the catchError prop type. The fallback can be defined as a pure value, Muster NodeDefinition or a fallback generator function. The fallback generator function is a function that gets called when an error is encountered, and is expected to return a NodeDefinition that can be used as a fallback.

    example

    Replacing an error with a string

    import { container, error, propTypes } from '@dws/muster-react';
    
    const myContainer = container({
      graph: {
        name: error('Some error'),
      },
      props: {
        name: propTypes.catchError('Something went wrong', true),
      },
    });
    
    const MyComponent = myContainer(({ name }) => <h1>{name}</h1>);
    // Rendered JSX:
    // <h1>Something went wrong</h1>

    This example shows how to handle graph errors by replacing the error with a fallback value (in this case a string). If the name prop was changed to name: true the component wouldn't render at all.

    example

    Replacing a branch error with a string

    import { container, error, propTypes } from '@dws/muster-react';
    
    const myContainer = container({
      graph: {
        user: {
          firstName: 'Bob',
          lastName: error('Some error'),
        },
      },
      props: {
        user: propTypes.catchError('Something went wrong', {
          firstName: true,
          lastName: true,
        }),
      },
    });
    
    const MyComponent = myContainer(({ user }) => {
      if (typeof user === 'string') return <h1>Error: {user}</h1>;
      return <p>{user.firstName} {user.lastName}</p>;
    });
    // Rendered JSX:
    // <h1>Error: Something went wrong</h1>

    This example shows how to handle branch-level graph errors by replacing the branch that returned an error with a string. In both examples the replacement value was a string, but it doesn't have to be.

    example

    Replacing a branch error with an object

    import { container, error, propTypes } from '@dws/muster-react';
    
    const myContainer = container({
      graph: {
        user: {
          firstName: 'Bob',
          lastName: error('Some error'),
        },
      },
      props: {
        user: propTypes.catchError({ error: 'Custom error' }, {
          firstName: true,
          lastName: true,
        }),
      },
    });
    
    const MyComponent = myContainer(({ user }) => {
      if (user.error) return <h1>Error: {user.error}</h1>;
      return <p>{user.firstName} {user.lastName}</p>;
    });
    // Rendered JSX:
    // <h1>Error: Custom error</h1>

    This example shows how to handle branch-level graph errors by replacing the branch with an object. The fallback object doesn't have to be of the same shape as the expected branch.

    Type parameters

    • T

    • O

    • M: Matcher<T, O>

    Parameters

    Returns CatchErrorMatcher<T, O | any, M | TreeMatcher<T>>

container

createContainer

createContainerFactory

createDisposeEmitter

createInitialRenderOperation

createMusterScenarioBuilder

createRunner

  • createRunner(): ScenarioBuilder<MusterReactScenarioState, undefined | NodeDefinition<any, any, any, object, any, StaticNodeType<any, any, any> | StatelessNodeType<any, any, any, string, GraphOperation<string, object, object, OperationType<string, object, object>>> | StatefulNodeType<any, any, any, object, any, string, GraphOperation<string, object, object, OperationType<string, object, object>>>> | function, MusterReactScenarioOutput, MusterReactExpectedResult>

defer

  • Creates a matcher used as part of the props section of the container and simpleContainer. Normally the Muster React component waits for all requested properties to resolve to a non-pending nodes. This prevents component from being rendered in an inconsistent state. However, this matcher informs muster-react that a given property can sometimes resolve to a pending node, and when that happens Muster should replace the pending value with either a fallback value, or with null when no fallback is given. The fallback can be defined as an JS value, a Muster node, or a fallback generator function. The fallback generator function receives a previous value of deferred node, or undefined if there was no previous value, and is expected to return a Muster node.

    example

    Deferring a leaf

    import { container, fromPromise, propTypes } from '@dws/muster-react';
    
    let resolvePromise;
    
    const myContainer = container({
      graph: {
        firstName: fromPromise(() =>
          new Promise((resolve) => { resolvePromise = resolve; }),
        ),
      },
      props: {
        firstName: propTypes.defer(true),
      },
    });
    
    const MyComponent = myContainer(({ firstName }) => <h1>{firstName || 'Loading...'}</h1>);
    
    // Rendered JSX:
    // <h1>Loading...</h1>

    This example shows how to use the defer prop type to instruct muster-react not to wait for a given property to load before rendering the component. During the first render the firstName property is equal to null. Calling the resolvePromise with a value will cause a new render of this component with a firstName equal to that value.

    example

    Deferring a branch

    import { container, fromPromise, propTypes } from '@dws/muster-react';
    
    let resolvePromise;
    
    const myContainer = container({
      graph: {
        user: fromPromise(() =>
          new Promise((resolve) => { resolvePromise = resolve; }),
        ),
      },
      props: {
        user: propTypes.defer({
          firstName: true,
          lastName: true,
        }),
      },
    });
    
    const MyComponent = myContainer(({ user }) => {
      if (!user) return <h1>Loading...</h1>;
      return <h1>Hello, {user.firstName} {user.lastName}</h1>;
    });
    
    // Rendered JSX:
    // <h1>Loading...</h1>

    This example show that the defer can also be used to defer branches.

    example

    Providing a static fallback value

    import { container, fromPromise, propTypes } from '@dws/muster-react';
    
    let resolvePromise;
    
    const myContainer = container({
      graph: {
        firstName: fromPromise(() =>
          new Promise((resolve) => { resolvePromise = resolve; }),
        ),
      },
      props: {
        firstName: propTypes.defer('Loading first name', true),
      },
    });
    
    const MyComponent = myContainer(({ firstName }) => <h1>{firstName}</h1>);
    
    // Rendered JSX:
    // <h1>Loading first name</h1>

    This example shows how to use the defer to provide a primitive fallback value for a deferred property.

    example

    Defer a list

    import { container, fromPromise, propTypes } from '@dws/muster-react';
    
    let resolvePromise;
    
    const myContainer = container({
      graph: {
        friends: fromPromise(() =>
          new Promise((resolve) => { resolvePromise = resolve; }),
        ),
      },
      props: {
        friends: propTypes.defer('Loading friends...', propTypes.list({
          id: true,
          firstName: true,
          lastName: true,
        })),
      },
    });
    
    const MyComponent = myContainer(({ friends }) => {
      if (!Array.isArray(friends)) return <h1>{friends}</h1>;
      return (
        <ul>
          {friends.map((friend) =>
            <li key={friend.id}>{friend.firstName} {friend.lastName}</li>
          )}
        </ul>
      )
    });
    
    // Rendered JSX:
    // <h1>Loading friends...</h1>

    This example shows that the defer can also be used to defer lists. The fallback value is defined as string, but could also be defined as an empty array, or as any object you want.

    Type parameters

    • T

    • O

    • M: Matcher<T, O>

    Parameters

    Returns DeferMatcher<T, O, M>

  • Type parameters

    • T

    • O

    • M: Matcher<T, O>

    Parameters

    • type: M

    Returns DeferMatcher<T, O, M>

  • Type parameters

    • T

    Parameters

    Returns DeferMatcher<T, any, TreeMatcher<T>>

  • Type parameters

    • T

    Parameters

    Returns DeferMatcher<T, any, TreeMatcher<T>>

  • Parameters

    Returns DeferMatcher<any, any, GetterMatcher<any, any, any>>

  • Parameters

    • prop: true

    Returns DeferMatcher<any, any, GetterMatcher<any, any, any>>

disposeContainerRoot

disposeDataSubscription

disposePendingCallsAndSets

disposeSettersAndCallersSubscription

extractKeyName

  • extractKeyName(name: string): string

formatPath

  • formatPath(path: Array<string>): string

getComponentGraph

getDisplayName

  • getDisplayName(component: ComponentClass<any> | StatelessComponent<any>): string

getInjectedProps

  • getInjectedProps(prefix: string, treeMatcher: TreeMatcher<any>, props: any, path: Array<string>): any

getMuster

  • getMuster(componentName: string, props: MusterProps, context?: any): Muster

getViewRootWrapper

  • getViewRootWrapper(view: ReactWrapper | ShallowWrapper, options: object): ReactWrapper | ShallowWrapper

getter

  • getter(): GetterMatcher<undefined, any, Matcher<any, never>>
  • getter(name: string): GetterMatcher<string, any, Matcher<any, never>>
  • getter<PT, PP, P>(type: P): GetterMatcher<undefined, PT, P>
  • getter<PT, PP, P>(name: string, type: P): GetterMatcher<string, PT, P>
  • Creates a matcher used as part of the props section of the container and simpleContainer. This matcher informs muster-react that a given property is a leaf in the graph, and that the component expects the value of that leaf. Consider a following definition of a simpleContainer:

    simpleComponent({
      firstName: true,
    });

    The firstName is defined as true, which is a shorthand for propTypes.getter(types.any). Muster React provides also one more shorthand for getter, which allows to specify the expected type of a property:

    simpleComponent({
      firstName: types.string,
    });

    In this example the firstName is defined as types.string, which is a shorthand for propTypes.getter(types.string). Additionally, normally Muster React component waits for all requested properties to resolve to a non-pending nodes, which prevents the component from being rendered in an inconsistent state. This behaviour can be changed in two ways:

    • By wrapping a specific property in a defer prop type
    • By creating a container with a renderLoading property set to true, or to a custom render function
    example

    Simple getter

    import { container } from '@dws/muster-react';
    
    const myContainer = container({
      graph: {
        firstName: 'Bob',
        lastName: 'Smith',
      },
      props: {
        firstName: true,
        lastName: true,
      },
    });
    
    const MyComponent = myContainer(({ firstName, lastName }) => (
      <h1>{firstName} {lastName}</h1>
    ));
    
    // Rendered JSX:
    // <h1>Bob Smith</h1>

    This example shows how to use the simplest way of defining a getter props. This getter shorthand doesn't validate the type of the value returned from the graph. The only validation it does is that it expects the firstName and lastName properties to not be pending before rendering the component.

    example

    Validate the type of a prop

    import { container, types } from '@dws/muster-react';
    
    const myContainer = container({
      graph: {
        fullName: 'Bob Smith',
        age: 25,
      },
      props: {
        fullName: types.string,
        age: types.number,
      },
    });
    
    const MyComponent = myContainer(({ fullName, age }) => (
      <h1>{fullName}, {age} yo</h1>
    ));
    
    // Rendered JSX:
    // <h1>Bob Smith, 25 yo</h1>

    This example shows how to add type validation to the props loaded from the graph. When the loaded property loaded from the graph is not of expected type, an error is raised, which prevents the component from being rendered. That error can be handled in a renderError function of the container.

    example

    Aliasing getters

    import { container, propTypes } from '@dws/muster-react';
    
    const myContainer = container({
      graph: {
        firstName: 'Bob',
        surname: 'Smith',
      },
      props: {
        firstName: true,
        lastName: propTypes.getter('surname'),
      },
    });
    
    const MyComponent = myContainer(({ firstName, lastName }) => <h1>{firstName} {lastName}</h1>);
    
    // Rendered JSX:
    // <h1>Bob Smith</h1>

    Just like in other Muster React prop types you can define aliases for properties loaded from the graph. In this example the component expects a lastName property, which in the graph is named surname. The container can define the lastName property as a getter for a surname leaf.

    example

    Aliasing getters with type validation

    import { container, propTypes, types } from '@dws/muster-react';
    
    const myContainer = container({
      graph: {
        firstName: 'Bob',
        surname: 'Smith',
      },
      props: {
        firstName: true,
        lastName: propTypes.getter('surname', types.string),
      },
    });
    
    const MyComponent = myContainer(({ firstName, lastName }) => <h1>{firstName} {lastName}</h1>);
    
    // Rendered JSX:
    // <h1>Bob Smith</h1>

    Building on the previous example, the getter prop type can also specify the expected type of the property loaded from the graph.

    Returns GetterMatcher<undefined, any, Matcher<any, never>>

  • Parameters

    • name: string

    Returns GetterMatcher<string, any, Matcher<any, never>>

  • Type parameters

    • PT

    • PP

    • P: Matcher<PT, PP>

    Parameters

    • type: P

    Returns GetterMatcher<undefined, PT, P>

  • Type parameters

    • PT

    • PP

    • P: Matcher<PT, PP>

    Parameters

    • name: string
    • type: P

    Returns GetterMatcher<string, PT, P>

global

  • global(...path: Array<NodeLike>): RootAndPath
  • global(path: Array<NodeLike>): RootAndPath

globalRoot

injected

  • Creates a new instance of the injected node, which is used when accessing a value of the injected property from within the local container graph.

    example

    Access injected property form local graph

    import { computed, container, injected, types } from '@dws/muster-react';
    
    container({
      require: {
        firstName: true,
      },
      graph: {
        greeting: computed(
          [injected('firstName')],
          (firstName) => `Hello, ${firstName}`,
        ),
      },
      props: {
        greeting: true,
      }
    });

    This example shows how to use the injected node to access the value of an injected property from within the local container graph.

    Parameters

    • Rest ...path: Array<string>

    Returns InjectedNodeDefinition

injected

  • Creates a matcher used as part of the props section of the container. This prop type is used to indicate to Muster React that the property is going to be loaded by the parent container, and that it will be injected to this container by its parent. This prop can't be used inside the simpleContainer as its definition doesn't allow defining required properties, which are necessary for the injected prop to work.

    example

    Inject property from the parent

    import { container, propTypes } from '@dws/muster-react';
    
    const childContainer = container({
      require: {
        firstName: true,
      },
      props: {
        firstName: propTypes.injected(),
      },
    });
    
    const ChildComponent = childContainer(({ firstName }) => <h1>Hello, {firstName}!</h1>);
    
    const parentContainer = container({
      data: {
        firstName: 'Bob',
      },
      props: {
        ...ChildComponent.getRequirements(),
      },
    });
    
    const ParentComponent = parentContainer((props) => (
      <section>
        <ChildComponent {...ChildComponent.inject(props)} />
        <p>Welcome to the App.</p>
      </section>
    ));
    
    // Rendered JSX:
    // <section>
    //   <h1>Hello, Bob</h1>
    //   <p>Welcome to the App.</p>
    // </section>

    This example shows how to use the injected prop type to load a prop that was marked as required, loaded from the parent component graph (by the means of ChildComponent.getRequirements(),), and then injected into the ChildComponent by the parent ({...ChildComponent.inject(props)}). This might seem like a complicated flow, which it is, but it has some benefits. A component that has all of its props marked as injected doesn't make a query to Muster graph itself. That job falls on the parent container. In this example only the ParentComponent makes a query to the muster graph to get its own properties, as well as the properties required by the ChildComponent.

    Parameters

    • Rest ...path: Array<string>

    Returns InjectedMatcher

isAsyncValueNodeDefinition

  • isAsyncValueNodeDefinition(value: NodeDefinition): boolean

isCallerArgumentMatcher

  • isCallerArgumentMatcher(value: any): boolean

isCallerMatcher

  • isCallerMatcher(value: any): boolean

isCatchErrorMatcher

  • isCatchErrorMatcher(value: any): boolean

isDeferMatcher

  • isDeferMatcher(value: any): boolean

isGetterMatcher

  • isGetterMatcher(value: any): boolean

isGlobalRootNodeDefinition

  • isGlobalRootNodeDefinition(value: any): boolean

isInjectedMatcher

  • isInjectedMatcher(value: any): boolean

isInjectedNodeDefinition

  • isInjectedNodeDefinition(value: any): boolean

isIsLoadingMatcher

  • isIsLoadingMatcher(value: any): boolean

isListMatcher

  • isListMatcher(value: any): boolean

isLoading

  • Creates a matcher used as part of the props section of the container and simpleContainer. This matcher is used in conjunction with the defer matcher to check if a given deferred property is pending.

    example

    Check if a deferred property is loading

    import { container, fromPromise, propTypes } from '@dws/muster-react';
    
    let resolvePromise;
    
    const myContainer = container({
      graph: {
        firstName: fromPromise(() =>
          new Promise((resolve) => { resolvePromise = resolve; }),
        ),
      },
      props: {
        firstName: propTypes.defer(true),
        isLoadingFirstName: propTypes.isLoading('firstName'),
      },
    });
    
    const MyComponent = myContainer(({ firstName, isLoadingFirstName }) => {
      if (isLoadingFirstName) return <h1>Loading...</h1>;
      return <h1>{firstName}</h1>;
    });
    
    // Rendered JSX:
    // <h1>Loading...</h1>

    This example shows how to use isLoading prop type to check if a sibling prop with a specified name. In the code above we're declaring a firstName prop as a deferred, and then declaring another property isLoadingFirstName, which checks if a prop firstName is loading. This prop will be true when the node requested by the firstName prop resolves to pending.

    One thing to remember is that the name taken by the isLoading prop must refer to the name of the sibling prop.

    example

    Another example of checking if deferred property is loading

    import { container, fromPromise, propTypes } from '@dws/muster-react';
    
    let resolvePromise;
    
    const myContainer = container({
      graph: {
        surname: fromPromise(() =>
          new Promise((resolve) => { resolvePromise = resolve; }),
        ),
      },
      props: {
        lastName: propTypes.defer(propTypes.getter('surname')),
        isLoadingLastName: propTypes.isLoading('lastName'),
      },
    });
    
    const MyComponent = myContainer(({ lastName, isLoadingLastName }) => {
      if (isLoadingLastName) return <h1>Loading...</h1>;
      return <h1>{lastName}</h1>;
    });
    
    // Rendered JSX:
    // <h1>Loading...</h1>

    This example serves as an explanation of the last sentence from the previous example. In the scenario, when the branch in the graph is called surname, and a prop that loads it is lastName, the correct way of checking if that prop is loading is to declare a prop isLoadingLastName: propTypes.isLoading('lastName'). Note that the isLoading takes lastName as an argument, instead of the name from the graph (surname).

    Parameters

    • relativePropName: string

    Returns IsLoadingMatcher

isPropNodeDefinition

  • isPropNodeDefinition(value: any): boolean

isProps

  • isProps(value: any): boolean

isSetterMatcher

  • isSetterMatcher(value: any): boolean

isSetterValueMatcher

  • isSetterValueMatcher(value: any): boolean

isTreeMatcher

  • isTreeMatcher(value: any): boolean

isValidInjectedPath

  • isValidInjectedPath(requiredPropsTree: TreeMatcher<any>, injectedPath: Array<string>): boolean

list

  • Creates a matcher used as part of the props section of the container and simpleContainer to indicate to Muster, that a given node is a collection, and that it should be loaded as an array. The list prop type can be created with no arguments, which means that the collection defined in the Muster graph is expected to be a collection of primitive values (value(1), value('some string'), value({ some: 'object' }), etc.). The list prop type can also be created with a matcher used to validate the type of these primitive values.

    Aside from loading the collection as an array of primitives, the list prop type enables loading collections containing tree nodes, by specifying which children should be loaded from them, which is similar to how tree matcher is used for specifying which children should be loaded from a given branch. In that case the list prop type internally creates a tree matcher to describe that behaviour.

    example

    Load a list of primitives

    import { container, propTypes } from '@dws/muster-react';
    
    const myContainer = container({
      graph: {
        names: ['Bob', 'Jane', 'Kate'],
      },
      props: {
        names: propTypes.list(),
      },
    });
    
    const MyComponent = myContainer(({ names }) => (
      <ul>
        {names.map((name) => <li>{name}</li>)}
      </ul>
    ));
    
    // Rendered JSX:
    // <ul>
    //   <li>Bob</li>
    //   <li>Jane</li>
    //   <li>Kate</li>
    // </ul>

    This example shows how to load a list of primitive values from Muster with the use of the list prop type.

    @example Load a list of primitives of a specified type

    import { container, propTypes, types } from '@dws/muster-react';
    
    const myContainer = container({
      graph: {
        names: ['Bob', 'Jane', 'Kate'],
      },
      props: {
        names: propTypes.list(types.string),
      },
    });
    
    const MyComponent = myContainer(({ names }) => (
      <ul>
        {names.map((name) => <li>{name}</li>)}
      </ul>
    ));
    
    // Rendered JSX:
    // <ul>
    //   <li>Bob</li>
    //   <li>Jane</li>
    //   <li>Kate</li>
    // </ul>

    This example shows how to load a list of primitive values from Muster with the use of the list prop type. Additionally the code makes sure that the items loaded from musters are strings.

    example

    Load a list of primitives under an alias

    import { container, propTypes } from '@dws/muster-react';
    
    const myContainer = container({
      graph: {
        myListName: ['Bob', 'Jane', 'Kate'],
      },
      props: {
        names: propTypes.list('myListName'),
      },
    });
    
    const MyComponent = myContainer(({ names }) => (
      <ul>
        {names.map((name) => <li>{name}</li>)}
      </ul>
    ));
    
    // Rendered JSX:
    // <ul>
    //   <li>Bob</li>
    //   <li>Jane</li>
    //   <li>Kate</li>
    // </ul>

    This example shows how to instruct the list prop type to load a collection with a name different than the name of the property.

    example

    Load a list with trees in it

    import { container, propTypes } from '@dws/muster-react';
    
    const myContainer = container({
      graph: {
        people: [
          { firstName: 'Bob', lastName: 'Smith' },
          { firstName: 'Jane', lastName: 'Jonson' },
          { firstName: 'Kate', lastName: 'Parker' },
        ],
      },
      props: {
        people: propTypes.list({
          firstName: true,
        }),
      },
    });
    
    const MyComponent = myContainer(({ people }) => (
      <ul>
        {people.map(({ firstName }) => <li>{firstName}</li>)}
      </ul>
    ));
    
    // Rendered JSX:
    // <ul>
    //   <li>Bob</li>
    //   <li>Jane</li>
    //   <li>Kate</li>
    // </ul>

    This example show how to load only specific branches from the people collection. The array loaded from Muster will contain objects with firstName, but without the lastName.

    Returns ListMatcher<any, undefined, undefined>

  • Parameters

    • name: string

    Returns ListMatcher<any, string, undefined>

  • Type parameters

    • TT

    • TP

    • T: Matcher<TT, TP>

    Parameters

    • itemType: T

    Returns ListMatcher<TT, undefined, T>

  • Type parameters

    • F

    Parameters

    Returns ListMatcher<F, undefined, TreeMatcher<F>>

  • Type parameters

    • TT

    • TP

    • T: Matcher<TT, TP>

    Parameters

    • name: string
    • itemType: T

    Returns ListMatcher<TT, string, T>

  • Type parameters

    • F

    Parameters

    • name: string
    • itemShape: Props<F>

    Returns ListMatcher<F, string, TreeMatcher<F>>

matcherToQueryPart

  • matcherToQueryPart(disposeEmitter: DisposeEmitter, matcher: Matcher<any>, name?: undefined | string): NodeDefinition | undefined

matcherToQueryPart

parseChildOperations

parseOperationAssert

  • parseOperationAssert(fn: function): function

parseOperations

parseScenario

parseScenarioOperations

prop

  • Creates a new instance of the prop node, which is used when accessing a value of a property from within the local container graph. See the Accessing react props from the local graph example in the README.md to learn more.

    example

    Access a property form local graph

    import { computed, container, prop, types } from '@dws/muster-react';
    
    const myContainer = container({
      graph: {
        greeting: computed(
          [prop('firstName')],
          (firstName) => `Hello, ${firstName}`,
        ),
      },
      props: {
        greeting: true,
      }
    });
    
    // Example usage:
    // const MyComponent = myContainer(({ greeting }) =>  <h1>{greeting}</h1>);
    // <MyComponent firstName="Bob" />

    This example shows how to use the prop node to access the value of a property from within the local container graph.

    Parameters

    • name: string

    Returns PropNodeDefinition

renderPlatformErrors

  • renderPlatformErrors(componentName: string, errors: Array<Error>): any

renderPlatformErrors

  • renderPlatformErrors(componentName: string, errors: Array<Error>): Element

sanitizeMatcher

  • sanitizeMatcher<T, O, M>(matcher: M): M | GetterMatcher<undefined, T, M>

sanitizeProps

setter

  • Creates a matcher used as part of the props section of the container and simpleContainer. This matcher informs muster-react that a given property should be loaded from the graph as a setter function. The returned function is an asynchronous function that returns a promise when called. Calling it will cause a matching settable node in the graph to be set with the help of a set() node.

    In order for the function returned from the graph to work correctly the node in your graph must support set operation. Examples of nodes that support the set operation: variable, fromPromise, placeholder. If the node targeted by the setter does not support the set operation then calling the returned function will result in the promise being rejected with an error.

    example

    Set the variable

    import { container, propTypes, variable } from '@dws/muster-react';
    
    const myContainer = container({
      graph: {
        firstName: variable('Bob'),
      },
      props: {
        firstName: propTypes.setter(),
      },
    });
    
    const MyComponent = myContainer(({ firstName }) => (
      <button onClick={() => firstName('Jane')}>Set firstName = 'Jane'</button>
    ));

    This example shows how to use the setter prop type to be able to set a value of a variable defined in the local container graph. The code above ignores the fact that the firstName is an asynchronous function that returns a promise, and just calls it every time the button is clicked. Also, the code above named the setter as firstName, but ideally the property should be called setFirstName to avoid clashing with an actual firstName property, which would could be loaded by the component. See the next example to find out how to alias setter props.

    example

    Alias the setter prop

    import { container, propTypes, variable } from '@dws/muster-react';
    
    const myContainer = container({
      graph: {
        firstName: variable('Bob'),
      },
      props: {
        setFirstName: propTypes.setter('firstName'),
      },
    });
    
    const MyComponent = myContainer(({ setFirstName }) => (
      <button onClick={() => setFirstName('Jane')}>Set firstName = 'Jane'</button>
    ));

    This example shows how to specify the alias for the setter prop. Using such alias frees the firstName name for a normal getter.

    example

    Validate the type of value

    import { container, propTypes, types, variable } from '@dws/muster-react';
    
    const myContainer = container({
      graph: {
        firstName: variable('Bob'),
      },
      props: {
        setFirstName: propTypes.setter('firstName', types.string),
      },
    });
    
    const MyComponent = myContainer(({ setFirstName }) => {
      async function onButtonClick() {
        console.log('Calling `setFirstName` with a string argument');
        try {
          await setFirstName('Jane');
          console.log('Success');
        } catch (ex) {
          console.log('Didn\'t work');
        }
    
        console.log('Calling `setFirstName` with a number argument');
        try {
          await setFirstName(123);
          console.log('Success');
        } catch (ex) {
          console.log('Didn\'t work');
        }
      }
      return <button onClick={onButtonClick}>Click me</button>;
    });
    
    // Console output after clicking the button:
    // Calling `setFirstName` with a string argument
    // Success
    // Calling `setFirstName` with a number argument
    // Didn't work

    This example shows how to specify the expected type of a value that can be passed to the setter. Calling the setter with a value of a correct type resolves with a value set to it, and calling the setter with a value of an incorrect type results in a promise being rejected with an error.

    Returns SetterMatcher<undefined, undefined>

  • Parameters

    • name: string

    Returns SetterMatcher<string, undefined>

  • Type parameters

    • PT

    • PP

    • P: Matcher<PT, PP>

    Parameters

    • type: P

    Returns SetterMatcher<undefined, P>

  • Type parameters

    • PT

    • PP

    • P: Matcher<PT, PP>

    Parameters

    • name: string
    • type: P

    Returns SetterMatcher<string, P>

setterValue

simpleContainer

toRequirementsTree

tree

  • Creates a matcher used as part of the props section of the container and simpleContainer. This matcher informs Muster that a given prop is a tree, and that Muster should get some children from it. The tree matcher is implicitly created by Muster React when defining props as a nested JS object: `js import { container } from '@dws/muster-react';

    container({ graph: { user: { firstName: 'Bob', lastName: 'Smith', }, }, props: { user: { firstName: true, lastName: true, }, }, });

    is equivalent to:
    ```js
    import { container, propTypes, types } from '@dws/muster-react';
    
    container({
      graph: {
        user: {
          firstName: 'Bob',
          lastName: 'Smith',
        },
      },
      props: {
        user: propTypes.tree({
          firstName: propTypes.getter(types.any),
          lastName: propTypes.getter(types.any),
        }),
      },
    });

    As you see the first syntax is much shorter, while still expressing the same set of props. The tree prop can also be nested to access some deeply nested properties:

    import { container } from '@dws/muster-react';
    
    container({
      graph: {
        applicationData: {
          user: {
            firstName: 'Bob',
            lastName: 'Smith',
          },
        }
      },
      props: {
        applicationData: {
          user: {
            firstName: true,
            lastName: true,
          },
        }
      },
    });

    Type parameters

    • T

    Parameters

    Returns TreeMatcher<T>

updatePropsStreams

  • updatePropsStreams<PF, P>(props: MusterReactProps<PF, P>): (Anonymous function)

Object literals

Const propTypes

propTypes: object

caller

caller: caller

callerArguments

callerArguments: callerArguments

catchError

catchError: catchError

defer

defer: defer

getter

getter: getter

injected

injected: injected

isLoading

isLoading: isLoading

list

list: list

setter

setter: setter

setterValue

setterValue: setterValue

tree

tree: tree