ctrlplusb / react-async-bootstrapper Goto Github PK
View Code? Open in Web Editor NEWExecute a bootstrap method on your React/Preact components. Useful for data prefetching and other activities.
License: MIT License
Execute a bootstrap method on your React/Preact components. Useful for data prefetching and other activities.
License: MIT License
Updated both my JavaScript and TypeScript example projects. Renamed asyncBootsrap to bootstrap and still get the warning:
"react-async-bootstrapper" deprecation notice: please rename your "asyncBootsrap" methods to "bootstrap"
JavaScript Changes
TypeScript Changes
HI, i'm trying to upgrade my universal application from react-router 3 to 4, and the only almost functioning async component its yours (I've tried react-loadable, but it flickers on first render...).
But I've noticed that calling asyncBootstrapper(content).then(...)
, trigger the rendering twice (4 times if we consider the ssr).
There is no solution to that problem? I've made something wrong?
My project experiment: https://github.com/cloud-walker/rr4-ssr-code-split-experiment
With the latest react version I'm unable to make this library work, for some reason react-tree-walker is not able to keep the context of the provider.
I was able to reproduce the error inside the asyncBootstrapper.test.js:
`
import React, { Component } from 'react'
import asyncBootstrapper from '../'
const ThemeContext = React.createContext('light')
describe('asyncBootstrapper()', () => {
let values = []
let actualContext
let contextValue
class DeprecatedAPI extends Component {
asyncBootstrap() {
values.push(this.props.id)
return true
}
render() {
return <div>{this.props.children}</div>
}
}
class NewAPI extends Component {
bootstrap() {
values.push(this.props.id)
actualContext = this.context
return true
}
render() {
return <div>{this.props.children}</div>
}
}
const app = Foo => (
<ThemeContext.Provider value='dark'>
beforeEach(() => {
values = []
})
it('deprecated API', () =>
asyncBootstrapper(app(DeprecatedAPI)).then(() =>
expect(values).toEqual([1, 2, 4, 3]),
))
it('new API', () =>
asyncBootstrapper(app(NewAPI), null, { bespokeContext: true }).then(() => {
expect(values).toEqual([1, 2, 4, 3])
expect(actualContext).toEqual({
bespokeContext: true,
reactAsyncBootstrapperRunning: true,
})
expect(contextValue).toEqual('dark')
}))
})
`
Updating the react version to 16.6.3 you should be able to reproduce the error.
const serialize = require("serialize-javascript");
const ejs = require('ejs');
const ReactDOMServer = require("react-dom/server");
const bootstrapper = require('react-async-bootstrapper')
const Helmet = require('react-helmet').default
const SheetsRegistry = require('react-jss').SheetsRegistry
const createGenerateClassName = require('@material-ui/core/styles').createGenerateClassName
const createMuiTheme = require('@material-ui/core/styles').createMuiTheme
const themeColors = require('../../client/themes/theme-default')
const getStoreState = (stores) => {
return Object.keys(stores).reduce((result, storeName) => {
result[storeName] = stores[storeName].toJson()
return result;
}, {})
}
module.exports = (bundle, template, req, res) => {
const user = req.session.user;
const createStoreMap = bundle.createStoreMap
const createApp = bundle.default
const routerContext = {};
const stores = createStoreMap();
const sheetsRegistry = new SheetsRegistry();
// Create a theme instance.
const theme = createMuiTheme(themeColors);
const generateClassName = createGenerateClassName();
if (user) {
stores.appState.user.isLogin = true;
stores.appState.user.info = user;
}
const app = createApp(stores, routerContext, sheetsRegistry, generateClassName, theme, req.url);
return new Promise((resolve, reject) => {
bootstrapper(app).then(() => {
console.log('==json==================');
console.log(JSON.stringify(routerContext, null, '\t'));
console.log('========================');
if (routerContext.url) {
res.status(302).setHeader('Location', routerContext.url)
res.end()
return
}
const helmet = Helmet.rewind();
const state = getStoreState(stores);
const content = ReactDOMServer.renderToString(app);
const html = ejs.render(template, {
appString: content,
initialState: serialize(state),
meta: helmet.meta.toString(),
title: helmet.title.toString(),
style: helmet.style.toString(),
link: helmet.link.toString(),
materialCss: sheetsRegistry.toString(),
})
res.send(html);
resolve()
}).catch(reject)
})
}
it will be rerender
As react router dom is the most used router for react. it will be nice to have an example of integrating the router with the bootstrapper to make sure the bootstrap function is called on route change (somehow)
Needs doing on react-tree-walker
likely
Hi,
I tried to follow the example in the docs and for some reason the asyncBootstrap function is not called inside Product.
i'm using create-react-app.
Did it happen to you maybe ?
I use + react-async-bootstrapper for react ssr development, it will report an error in the development environment, the production environment is normal, how should this problem be solved, thank you
"TypeError: Cannot read property 'dense' of undefined\n
at Object.children (server-entry.js:29:31469)\n
at recursive (/Users/ender/learning/github/react-cnode/node_modules/react-tree-walker/dist/react-tree-walker.js:129:41)\n
at /Users/ender/learning/github/react-cnode/node_modules/react-tree-walker/dist/react-tree-walker.js:153:26\n
at <anonymous>\n
at process._tickCallback (internal/process/next_tick.js:189:7)"
This is my code:
TopicDetail.jsx
class TopicDetail extends React.Component{ constructor(){ super(); this.state={ newReply:'' } } componentDidMount(){ // const id = this._getId(); // this.props.topicStore.getTopicDetail(id); } bootstrap(){ const id = this._getId(); return this.props.topicStore.getTopicDetail(id).then(() => { return true }).catch(() => { return false }); }}
The method of request, written in mobx:
@action fetchTopics(tab){ //console.log('tab',tab) return new Promise((resolve,reject) => { // console.log('syncing', this.syncing) this.syncing = true this.topics= [] get('/api/topics',{ mdrender:false, tab:tab }).then(resp => { // console.log('resp',resp) if(resp.success){ resp.data.forEach(topic => { // console.log('topic',topic) this.addTopic(topic) }) resolve() }else{ reject() } }).catch(err => { reject(err) this.syncing = false }) }) }
the get method
export const get = (url,param) => { //console.log('url',url) let params = param || {} return new Promise ((resolve,reject) => { console.log('axios') axios({ method:'get', url, params, }).then((resp) => { console.log('resp1', resp) const data = resp.data; if(data && data.success === true){ resolve(data) }else{ reject(data) } }).catch((err) => { if(err.response){ reject(err.response.data) }else{ reject({ sucess:false, err_msg:err.message }) } }) }) }
server.js
app.use('/api/user', require('./util/handle-login')) app.use('/api', require('./util/proxy'))
I found that I did not intercept 'api' at all.
This problem has been solved for a long time and I hope to get your help.
Thank you!
when i use dynamic import in react router as follows, the following problem has occurred
the error only occurred in development mode, not in production mode
import React from 'react'
import { Route, Redirect, withRouter, } from 'react-router-dom'
import Loadable from 'react-loadable'
import CircularProgress from '@material-ui/core/CircularProgress'
// right
// import TopicList from 'views/topic-list'
// import TopicDetail from 'views/topic-detail'
// import TopicCreate from 'views/topic-create'
// import UserLogin from 'views/user/login'
// import UserInfo from 'views/user/info'
// wrong
const TopicList = Loadable({
loader: () => import('views/topic-list'),
loading() {
return <CircularProgress />
},
})
const TopicDetail = Loadable({
loader: () => import('views/topic-detail'),
loading() {
return <CircularProgress />
},
})
const TopicCreate = Loadable({
loader: () => import('views/topic-create'),
loading() {
return <CircularProgress />
},
})
const UserLogin = Loadable({
loader: () => import('views/user/login'),
loading() {
return <CircularProgress />
},
})
const UserInfo = Loadable({
loader: () => import('views/user/info'),
loading() {
return <CircularProgress />
},
})
export default () => [
<Route exact render={() => <Redirect to="/list" />} path="/" key="home" />,
<Route component={TopicList} path="/list" key="list" />,
<Route component={TopicDetail} path="/detail/:id" key="detail" />,
]
{ Error: Cannot find module './0.server-entry.js'
at Function.Module._resolveFilename (module.js:548:15)
at Function.Module._load (module.js:475:25)
at Module.require (module.js:597:17)
at require (internal/module.js:11:18)
at Function.requireEnsure [as e] (server-entry.js:46:25)
at loader (webpack:///./client/router/index.jsx?:69:60)
at load (/Users/ender/learning/github/react-cnode/node_modules/react-loadable/lib/index.js:28:17)
at init (/Users/ender/learning/github/react-cnode/node_modules/react-loadable/lib/index.js:121:13)
at new LoadableComponent (/Users/ender/learning/github/react-cnode/node_modules/react-loadable/lib/index.js:150:7)
at /Users/ender/learning/github/react-cnode/node_modules/react-tree-walker/dist/react-tree-walker.js:174:30 code: 'MODULE_NOT_FOUND' }
Before upgrading, it will wait for API called even at the first time and render whole page, but after upgrading, no list content is renderer at the first time.
You can check https://github.com/JounQin/react-hackernews and run yarn dev
and visit http://localhost:4000 to view the correct SSR page, then simply upgrade react-async-bootstrapper
to 2.0.0
, then you will see incorrect page at first rendering.
Online Link: https://react-hn.now.sh/ (not upgrade yet)
I don't know if it is related to [email protected]
or [email protected]
is not compatible with [email protected]
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.