Giter Club home page Giter Club logo

react-isomorphic-data's People

Contributors

dependabot[bot] avatar jackyef avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

react-isomorphic-data's Issues

Add test-utils

Test-utils will contain things needed for consumer to test their app

Application performance after implementing react-isomorphic-data

We've been looking at introducing react-isomorphic-data to Simorgh and have noticed that just implementing this library and not including any extra data fetches has nearly doubled the latency/response time of the application. Including 1 extra data fetch nearly triple's the response time when server side rendering.

Is this something you have observed before? or something you are aware of?

This is our application running against the latest (master) branch without the library.

Stat 2.5% 50% 97.5 99% Avg Stdev Max
Latency 223 ms 276 ms 425 ms 541 ms 288.31 ms 53.61 ms 648.6 ms

This is the application with this library introduced, however with no extra data fetching.

Stat 2.5% 50% 97.5 99% Avg Stdev Max
Latency 415 ms 478 ms 995 ms 1088 ms 513.42 ms 120.85 ms 1112.93 ms

And this is with 1 data fetch using the useData() hook

Stat 2.5% 50% 97.5 99% Avg Stdev Max
Latency 619 ms 737 ms 1239 ms 1329 ms 769.81 ms 142.54 ms 1363.48 ms

Error while trying to getDataFromTree TypeError: Object(...) is not a function

I get the following error in the console log when I run my server:

Error while trying to getDataFromTree TypeError: Object(...) is not a function
    at _callee$ (webpack:///./server/src/utils/serverUtils.js?:68:97)
    at tryCatch (/Users/username/codex/myprojects/bunch/current/node_modules/babel-polyfill/node_modules/regenerator-runtime/runtime.js:65:40)
    at Generator.invoke [as _invoke] (/Users/username/codex/myprojects/bunch/current/node_modules/babel-polyfill/node_modules/regenerator-runtime/runtime.js:303:22)
    at Generator.prototype.<computed> [as next] (/Users/username/codex/myprojects/bunch/current/node_modules/babel-polyfill/node_modules/regenerator-runtime/runtime.js:117:21)
    at asyncGeneratorStep (webpack:///./server/src/utils/serverUtils.js?:18:103)
    at _next (webpack:///./server/src/utils/serverUtils.js?:20:194)
    at eval (webpack:///./server/src/utils/serverUtils.js?:20:364)

I was following the example given here to https://react-isomorphic-data.netlify.app/docs/ssr/getdatafromtree implement in my project.

If I change my project to use this: https://react-isomorphic-data.netlify.app/docs/ssr/rendertostringwithdata it works perfectly fine.

My packages:-
"react": "16.13.1"
"react-dom": "16.13.1"
"react-helmet": "6.0.0"
"react-isomorphic-data": "0.16.0"
"express": "4.17.1"
"isomorphic-fetch": "2.2.1"
"react-redux": "7.2.0"
"redux": "4.0.5"
"redux-thunk": "2.3.0"

Since renderToStringWithData is working fine and I'm fine using it, but I thought I'll report just in case you would want to take a look and fix it at why getDataFromTree not working.

My implementation was something like this.

export const reactRender = async (req, res) => {
   const {routes, store} = res.locals
   const dataClient = createDataClient({
     initialCache: {},
     ssr: true,
     headers: {
        'cookie': req.header('cookie'),
        'User-Agent': req.header('User-Agent'),
        'X-Forwarded-For': req.header('X-Forwarded-For'),
        'X-Real-IP': req.header('X-Real-IP'),
        'Accept': req.header('Accept'),
        'Host': req.header('Host')
     }
  })

  const tree = (
    <DataProvider client={dataClient}>
      <Provider store={store}>
         <AppContext.Provider
            value={context}>
            <StaticRouter location={req.url}>
               {routes}
             </StaticRouter>
         </AppContext.Provider>
      </Provider>
    </DataProvider>
  )

  let html
  try {
     await getDataFromTree(tree, dataClient)
     html = renderToString(tree)
  } catch (err) {
     console.error('Error while trying to getDataFromTree', err)
  }

  Object.assign(res.locals, {
     cache: dataClient.cache,
     appHtml: html
  })
}

I call this function in my index.js in express server as follows:

await reactRender(req, res)
res.set('Content-Type', 'text/html')
res.status(200).end(lodashTpl(res.locals))

Let me know if you need any other information from my side. Thanks.

Have some sort of a plan to achieve v1

Since this library isn't exactly used by a lot of people, this might be tough to do.

What I am thinking right now is that we can:

  1. Make sure we are satisfied with the overall API designs
  2. Make sure we are confident enough that our tests have covered most cases
  3. Have a release candidate ready, whatever version it might be
  4. Spread on twitter? medium?

Improve cache normalisation

Currently, the cache is a very simple object with an absolute URL as key, and an object as the value of the key.

window.__cache= {
	"http://localhost:3000/some-rest-api/1": {"message":"/some-rest-api/1","randomNumber":79},
	"http://localhost:3000/some-rest-api/123": {"message":"/some-rest-api/123","randomNumber":47}
	"http://localhost:3000/some-rest-api/345": {"message":"/some-rest-api/123","randomNumber":23}
}

At a glance, we should be able to write this cache as:

window.__cache= {
  "http://localhost:3000": {
    "/some-rest-api": {
      "/1": {"message":"/some-rest-api/1","randomNumber":79},
      "/123": {"message":"/some-rest-api/123","randomNumber":47},
      "/345": {"message":"/some-rest-api/123","randomNumber":23}
    }
  }
}

or even:

window.__cache= {
  "http": {
	"localhost:3000": {
	  "some-rest-api": {
        "1": {"message":"/some-rest-api/1","randomNumber":79},
	    "123": {"message":"/some-rest-api/123","randomNumber":47},
	    "345": {"message":"/some-rest-api/123","randomNumber":23}
	  }
	}
  }
}

In larger objects, especially if many of the base path of the APIs are the same, this can save a lot size, which means smaller initial HTML document size.

Add TypeScript support

User of the library should be able to define what they data is going to look like. Something like

interface MyData {
  foo: string;
  bar: number;
}

const { data, error, error } = useData<MyData>(url);

feat: Support methods other than GET

Currently we are hardcoding the method to GET.

We can actually open this up to support all other methods for useLazyData. For useData we still only allow GET request. This can add more functionalities, such as POST-ing data on button click, etc.

lifecycle component?

Any example with the life cycle of a traditional component?

class Component extends React.Component {

  state = { data: [] };

  async componentDidMount(){
    const data = await useData(API);
    this.setState({ data });
  }

  render(){
     console.log('data', data)
  }
}

I have not tried

Implement subscription model for better performance

Context + hooks will cause many re-renders.

Consider using subscription model like redux did to improve on this situation.

facebook/react#15156

We can learn from redux journey https://blog.isquaredsoftware.com/2018/11/react-redux-history-implementation/
https://github.com/reduxjs/react-redux/blob/master/src/hooks/useSelector.js

Sebastian from facebook team also says that the new Context API is not meant to be used to propagate state: https://twitter.com/sebmarkbage/status/1219836431972978689

I am now thinking of either add a tip in the docs to let users memoize their expensive tree themselves, instead of doing this from the library itself, since React does not seem to provide a good way to do this at the moment.

Add tests and coverage

To prevent regressions in the future, this will be nice to have so the library can be more stable.

feat: More refined fetchPolicy options

Currently, if a request to a specific URL already has a response in cache, it will always use the one in cache. Basically, the behavior now is like cache-first in react-apollo.

The library should be able to handle more policies such as cache-and-network and network-only. This will also have some effect on how fetching data during SSR works.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.