Options
All
  • Public
  • Public/Protected
  • All
Menu

React-Pond

Use the Actyx Pond framework fully integrated into React. Expand your toolchain with <Pond>, useFish, and usePond to speed up your UI projects and write distributed apps in a couple of hours.

📦 Installation

React-Pond is available as a npm package.

npm install @actyx-contrib/react-pond

📖 Documentation and detailed examples

You can access the full API documentation and related examples by visiting: https://actyx-contrib.github.io/react-pond

You will find detailed examples here. They can be executed running e.g. `npm run example:chatRoom'.

🤓 Quick start

🌊 <Pond>...</Pond>

Wrap your application with the <Pond> to use you fish everywhere in the code.

Example

ReactDOM.render(
  <Pond
    onError={() => {
      setTimeout(() => location.reload(), 5000)
      return <div>Connection to Actyx rejected: {JSON.stringify(e)}. Next reconnect in 5 seconds.</div>
    }}
  >
    <AmazingDistributedApp />
  </Pond>,
  document.getElementById('root')!,
)

🐟 useFish and useFishFn

Write your distributed logic with the well-known fish and get the state as easy as possible.

  • useFish(fish): Hydrate one explicit fish without a factory
  • useFishFn(fishFactory, properties): Use a factory function to hydrate fish with properties

📖 Example

const MaterialRequest = ({ id }: Props) => {
  const allOpenMatReq = useFish(MatRequest.allOpen)
  const matReq = useFishFn(MatRequest.of, id)

  return (
    <div>
      <div>Open Material Requests: {allOpenMatReq.ids.length}</div>
      <div>
        Material Request ({id}): {matReq.state.status}
      </div>
      <button
        onClick={() =>
          matReq.run((_state, enqueue) => enqueue(Tag('material').withId(id), EventType.Done))
        }
      >
        Done
      </button>
    </div>
  )
}

🎏 useRegistryFish

Map your registry fish to the entities and create tables, lists, complex autocomplete fields, ...

📖 Example

const MaterialRequests = () => {
  const allOpenMatReq = useRegistryFish(MatRequest.allOpen, reg => reg.ids, MatRequestFish.of)

  const done = (matReq: ReactFish<State, Events, string>) => {
    matReq.run((_state, enqueue) => enqueue(Tag('material').withId(matReq.props), EventType.Done))
  }

  return (
    <div>
      <div>Open Material Requests: {allOpenMatReq.length}</div>
      {allOpenMatReq.map(matReq => (
        <div key={matReq.props}>
          <div>
            {matReq.props}: {matReq.state.status}
          </div>
          <button onClick={() => done(matReq)}>Done</button>
        </div>
      ))}
    </div>
  )
}

🌊 usePond

The pond is not hidden from you. Use it as usual with const pond = usePond().

📖 Example

const Example = () => {
  const pond = usePond()
  const [nodeConnectivity, setNodeConnectivity] = React.useState<ConnectivityStatus>()
  React.useEffect(() => {
    pond.getNodeConnectivity({ callback: setNodeConnectivity })
  }, [])

  return <div>
    <div>{JSON.stringify(nodeConnectivity)}</div>
  </div>
}

Index

Type aliases

PondProps

PondProps: { children: React.ReactNode; loadComponent?: JSX.Element; onError?: undefined | ((error: unknown) => void | Element); onStoreConnectionClosed?: undefined | (() => void); pondOptions?: PondOptions; url?: undefined | string }

Pond component properties to get some feedback

Type declaration

  • children: React.ReactNode

    React application. Components are shown when the initialize is done

  • Optional loadComponent?: JSX.Element

    Component to show during the connect (very shortly)

  • Optional onError?: undefined | ((error: unknown) => void | Element)

    Error callback the the pond is not able to reach actyxOS locally

  • Optional onStoreConnectionClosed?: undefined | (() => void)

    Hook, when the connection to the store is closed

  • Optional pondOptions?: PondOptions

    Advanced configuration options for the Pond.

  • Optional url?: undefined | string

    optional url to overwrite to local connection and connect to an other peer (default: ws://localhost:4243/store_api)

ReactFish

ReactFish<State, Event, Props>: { props: Props; run: (eff: StateEffect<State, Event>) => Promise<void>; state: State }

ReactFish type.

This fish will handle all interactions with the React component.

Type parameters

  • State

  • Event

  • Props

Type declaration

  • props: Props

    props of the fish

  • run: (eff: StateEffect<State, Event>) => Promise<void>

    run function for the observed fish

      • (eff: StateEffect<State, Event>): Promise<void>
      • Parameters

        • eff: StateEffect<State, Event>

        Returns Promise<void>

  • state: State

    current public state of the observed fish

Functions

Const Pond

  • Pond(__namedParameters: { children: undefined | null | string | number | false | true | {} | ReactElement<any, string | ((props: P) => ReactElement | null) | {}> | ReactNodeArray | ReactPortal; loadComponent: undefined | Element; onError: undefined | ((error: unknown) => void | Element); onStoreConnectionClosed: undefined | (() => void); pondOptions: undefined | { currentPsnHistoryDelay?: undefined | number; defaultSnapshotThreshold?: undefined | number; fishErrorReporter?: FishErrorReporter; hbHistDelay?: undefined | number; stateEffectDebounce?: undefined | number; updateConnectivityEvery?: Milliseconds }; url: undefined | string }): Element
  • Top level component to initialize the pond

    Example:

    ReactDOM.render(
      <Pond>
        <App />
      </Pond>,
      document.getElementById('root')
    )

    Parameters

    • __namedParameters: { children: undefined | null | string | number | false | true | {} | ReactElement<any, string | ((props: P) => ReactElement | null) | {}> | ReactNodeArray | ReactPortal; loadComponent: undefined | Element; onError: undefined | ((error: unknown) => void | Element); onStoreConnectionClosed: undefined | (() => void); pondOptions: undefined | { currentPsnHistoryDelay?: undefined | number; defaultSnapshotThreshold?: undefined | number; fishErrorReporter?: FishErrorReporter; hbHistDelay?: undefined | number; stateEffectDebounce?: undefined | number; updateConnectivityEvery?: Milliseconds }; url: undefined | string }

      reactProperties for the pond @see PondProps

      • children: undefined | null | string | number | false | true | {} | ReactElement<any, string | ((props: P) => ReactElement | null) | {}> | ReactNodeArray | ReactPortal
      • loadComponent: undefined | Element
      • onError: undefined | ((error: unknown) => void | Element)
      • onStoreConnectionClosed: undefined | (() => void)
      • pondOptions: undefined | { currentPsnHistoryDelay?: undefined | number; defaultSnapshotThreshold?: undefined | number; fishErrorReporter?: FishErrorReporter; hbHistDelay?: undefined | number; stateEffectDebounce?: undefined | number; updateConnectivityEvery?: Milliseconds }
      • url: undefined | string

    Returns Element

    React component

Const useFish

  • useFish<State, Events>(fish: Fish<State, Events>): ReactFish<State, Events, void>
  • Stateful integration of an actyx Pond Fish.

    Learn more about the fish: https://developer.actyx.com/docs/pond/getting-started

    Example:

    export const App = () => {
      const chatRoomsFish = useFish(ChatRoomFish.channelList)
    
      return (
        <div>
          <div>List of existing chat rooms</div>
          <ul>
            {chatRoomsFish.map((name) => <li key={name}>{name}</li>)}
          </ul>
        </div>
      )
    }

    Type parameters

    • State

    • Events

    Parameters

    • fish: Fish<State, Events>

      fish to get the public state for

    Returns ReactFish<State, Events, void>

    ReactFish

Const useFishFn

  • useFishFn<State, Events, Props>(mkFish: (props: Props) => Fish<State, Events>, props: Props | undefined): ReactFish<State, Events, Props> | void
  • Stateful integration of an actyx Pond Fish factory.

    Learn more about the fish: https://developer.actyx.com/docs/pond/getting-started

    Example:

    export const App = () => {
      const [channel, setChannel] = React.useState('lobby')
      const chatRoomFish = useFishFn(ChatRoomFish.forChannel, channel)
    
      const send = () =>
        chatRoomFish && chatRoomFish.run((_state, enqueue) =>
          enqueue(ChatRoom.tags.channel.withId(channel), {
            type: 'message',
            message,
            sender: userName,
            channel
          })
        )
    
      return (
        <div>
          {chatRoomFish && (
            <>
              <div>current chat room: {chatRoomFish.props}</div>
              <div>
                {chatRoomFish.state.map((message, idx) => (
                  <div key={idx}>{message}</div>
                ))}
              </div>
              <div>
                <button onClick={send}>send</button>
              </div>
            </>
          )}
        </div>
      )
    }

    Type parameters

    • State

    • Events

    • Props

    Parameters

    • mkFish: (props: Props) => Fish<State, Events>
        • (props: Props): Fish<State, Events>
        • Parameters

          • props: Props

          Returns Fish<State, Events>

    • props: Props | undefined

      props for the factory

    Returns ReactFish<State, Events, Props> | void

    ReactFish | undefined If the props are undefined

Const usePond

  • usePond(): PondType
  • Get the pond in your react application.

    Learn more about the pond: https://developer.actyx.com/docs/pond/getting-started

    emit<E>(tags: Tags<E>, event: E): PendingEmission;
    observe<S, E>(fish: Fish<S, E>, callback: (newState: S) => void): CancelSubscription;
    run<S, EWrite>(fish: Fish<S, any>, fn: StateEffect<S, EWrite>): PendingEmission;
    keepRunning<S, EWrite>(fish: Fish<S, any>, fn: StateEffect<S, EWrite>, autoCancel?: (state: S) => boolean): CancelSubscription;
    dispose(): void;
    info(): PondInfo;
    getPondState(callback: (newState: PondState) => void): CancelSubscription;
    getNodeConnectivity(params: GetNodeConnectivityParams): CancelSubscription;
    waitForSwarmSync(params: WaitForSwarmSyncParams): void;
    throws

    Error if is not used before

    Returns PondType

    pond instance

Const useRegistryFish

  • useRegistryFish<RegState, State, Events, Props>(regFish: Fish<RegState, any>, map: (regState: RegState) => (undefined | Props)[], mkFish: (props: Props) => Fish<State, Events>): ReactFish<State, Events, Props>[]
  • Stateful integration of an actyx Pond Fish factory.

    Learn more about the fish: https://developer.actyx.com/docs/pond/getting-started

    Example:

    export const App = () => {
      const allChatRooms = useRegistryFish(ChatRoom.channelList, (s) => s, ChatRoom.forChannel)
    
      return (
        <div>
         {allChatRooms.map(f => (
           <div key={f.props}>{f.props}: {f.state.join(', ')}</div>
         ))}
        </div>
      )
    }

    Type parameters

    • RegState

    • State

    • Events

    • Props

    Parameters

    • regFish: Fish<RegState, any>

      fish to get the public state for, or fish factory function

    • map: (regState: RegState) => (undefined | Props)[]

      map the registry state to an array of properties used by the mkFish

        • (regState: RegState): (undefined | Props)[]
        • Parameters

          • regState: RegState

          Returns (undefined | Props)[]

    • mkFish: (props: Props) => Fish<State, Events>

      fish factory function to get the public state for

        • (props: Props): Fish<State, Events>
        • Parameters

          • props: Props

          Returns Fish<State, Events>

    Returns ReactFish<State, Events, Props>[]

    ReactFish[] entities of the registry

Legend

Generated using TypeDoc