Using Data from Host Platform

Lynx allows the client to provide an initial set of data when the page loads, and then update this data at any time afterward. This initial data is called initData.

Provide and Update Data

Prerequisites

You need to complete the instructions in Integrate with existing applications to ensure that your application has integrated Lynx and have a basic understanding of Lynx's Native API.

When using LynxView.loadTemplate() to load a Bundle, you have the opportunity to pass in some data:

LynxLoadMeta* meta = [LynxLoadMeta init];
// meta.url = @"";
// meta.binaryData = nil;
// meta.templateBundle = nil;
meta.initialData = __YOUR_DATA__;
// meta.loadOption = LynxLoadOptionDumpElement | LynxLoadOptionRecycleTemplateBundle;
[lynxView loadTemplate:meta];
LynxLoadMeta.Builder builder = new LynxLoadMeta.Builder();
// builder.setUrl();
// builder.setBinaryData();
// builder.setTemplateBundle();
builder.setInitialData(__YOUR_DATA__);
// builder.addLoadOption();
LynxLoadMeta meta = builder.build();
lynxView.loadTemplate(meta);

You can update this data later through LynxView.updateData() when needed:

LynxUpdateMeta* meta = [LynxUpdateMeta init];
meta.data = __YOUR_DATA__;
[lynxView updateData:meta];
LynxUpdateMeta.Builder builder = new LynxUpdateMeta.Builder();
builder.setUpdatedData(__YOUR_DATA__);
LynxUpdateMeta meta = builder.build();
lynxView.updateMetaData(meta);

The data you pass in when loading and the data you pass in when updating can be used on the frontend. Below is how to use this data on the front end.

Consuming the Data

On the frontend, you can retrieve initData by using useInitData(). When the client updates the data, these components will automatically re-render.

src/App.jsx
import { useInitData } from '@lynx-js/react';

export function App() {
  const initData = useInitData();
  return (
    <view>
      <text>{initData.greeting}</text>
    </view>
  );
}

If you are using class components, you can use InitDataConsumer.

import { Component, InitDataProvider, InitDataConsumer } from '@lynx-js/react';

class C extends Component {
  render() {
    return (
      <InitDataConsumer>
        {(initData) => (
          <view>
            <text>{initData.greeting}</text>
          </view>
        )}
      </InitDataConsumer>
    );
  }
}

InitDataConsumer must be used as a child node of InitDataProvider.

<InitDataProvider>
  <view>
    <C />
  </view>
</InitDataProvider>

Process Data Before Using It

While useInitData() gives you the initData from the client, it may not be in the format you expect.

Image you have the following disorganized initData:

  • On Android:

    {
      "pageTitle": "Hello Lynx"
    }
  • But, on iOS:

    {
      "page_title": "Hello Lynx"
    }

Your code may become less cleaner if you want to be compatible with both platforms:

import { useInitData } from '@lynx-js/react';

export function App() {
  const initData = useInitData();
  return (
    <view>
      <text>{initData.pageTitle || initData.page_title}</text>
    </view>
  );
}

The above scenarios are just examples, but Lynx do provide a way to process the initData before it is used, it is called dataProcessor.

Using defaultdataProcessor

If you (or the client developer) did not specify a processorName, Lynx will use the defaultDataProcessor to process the initData.

INFO

See lynx.registerDataProcessors for more examples.

src/index.tsx
import { root } from '@lynx-js/react';
import { App } from './App.js';

lynx.registerDataProcessors({
  defaultDataProcessor: function (rawInitData) {
    const { pageTitle, page_title, ...rest } = rawInitData;
    return {
      ...rest,
      pageTitle: pageTitle || page_title,
    };
  },
});
root.render(<App />);

if (import.meta.webpackHot) {
  import.meta.webpackHot.accept();
}

Then, in your component, you can use the initData directly:

src/App.jsx
import { useInitData } from '@lynx-js/react';

export function App() {
  const initData = useInitData();
  return (
    <view>
      <text>{initData.pageTitle}</text>
    </view>
  );
}

Using nameddataProcessor

You (or the client developer) can also specify a processorName when calling LynxView.updateData():

LynxUpdateMeta *meta = [[LynxUpdateMeta alloc] init];

// TODO: set data and processorName

[lynxView updateData:meta];
LynxUpdateMeta meta = new LynxUpdateMeta();

// TODO: set data and processorName

lynxView.updateMetaData(meta);

Accordingly, a named dataProcessor you defined will be called to process the initData, you can define multiple dataProcessors with syntax below:

src/index.tsx
import { root } from '@lynx-js/react';
import { App } from './App.js';

lynx.registerDataProcessors({
  dataProcessors: {
    someDataProcessor: function (rawInitData) {
      // process rawInitData
      return processedInitData;
    },
    anotherDataProcessor: function (rawInitData) {
      // process rawInitData
      return processedInitData;
    },
  },
});
root.render(<App />);

if (import.meta.webpackHot) {
  import.meta.webpackHot.accept();
}

This allows you (or the client developer) to decide on the client which dataProcessor to use if the business logic requires it.

Except as otherwise noted, this work is licensed under a Creative Commons Attribution 4.0 International License, and code samples are licensed under the Apache License 2.0.