davnicwil / react-frontload Goto Github PK
View Code? Open in Web Editor NEWAsync data loading for React components, on client & server
Async data loading for React components, on client & server
In the docs, I think you're missing an await
before the Promise.all
in the following code example:
const { data, frontloadMeta } = useFrontload('my-component', async ({ api }) => {
const [stuff, moreStuff] = Promise.all([
api.getStuff(),
api.getMoreStuff()
])
return { stuff, moreStuff }
})
should be:
const { data, frontloadMeta } = useFrontload('my-component', async ({ api }) => {
const [stuff, moreStuff] = await Promise.all([
api.getStuff(),
api.getMoreStuff()
])
return { stuff, moreStuff }
})
I looked for a documentation repo to PR, but couldn't find one.
Also, you may want to make it more obvious that the current docs are v2 in the callout that says:
v2 has just shipped! See here for the motivation for v2 and comparison with v1
Maybe something like:
These are the (just shipped) v2 docs! See here for the motivation for v2 and comparison with v1
Can you clarify how server rendered errors are handled? I'm trying to raise an error in the frontload to be handled in the node server render block, but I can't seem to catch the error anywhere. It seems like its being swallowed somewhere, but I can't figure it out.
If an error does throw on server render, it is not caught and populated in frontloadMetadata.error, instead it is just thrown and the entire render will fail. Such errors should be caught at the top level in your server render endpoint, and dealt with appropriately for your application.
This sounds like exactly what I want, but from what I can see, frontloadMetadata.error is populated, and the error is being caught.
frontload definitely sees the error
[react-frontload] Error on frontload [WaterbodyDetailLoader:lake-dorr], render pass 0
RecordNotFoundError: Request failed with status code 404
[stack trace]
{
name: 'RecordNotFoundError',
url: 'waterbodies/lake-dorr'
}
The component appears to keep rendering though, I see frontloadMeta.error true
logged in the server console from the component:
export const WaterbodyDetailLoader = (props: OwnProps) => {
const { urlSlug } = props;
const dispatch = useDispatch();
const { frontloadMeta } = useFrontload(
`WaterbodyDetailLoader:${urlSlug}`,
async () => {
try {
const waterbodyRes = await apiV1.waterbodyFetch(urlSlug);
} catch (e) {
if (e.response.status === 404) {
throw new RecordNotFoundError(e.message, e.response.config.url);
}
throw e;
}
console.log("WaterbodyDetailLoader complete");
return true;
}
);
console.log("frontloadMeta.error", frontloadMeta.error);
return <WaterbodyDetailContainer urlSlug={urlSlug} />;
};
Nothing is logged at the catch block of the server rendering block
try {
const { rendered, data } = await frontloadServerRender({
frontloadState,
render: () =>
renderToString(
extractor.collectChunks(
React.createElement(AppServer, {
location: req.url,
store,
routerContext,
frontloadState,
})
)
),
});
res.send(
DOCTYPE +
'\n' +
renderToString(
React.createElement(Html, {
content: rendered,
store,
xForwardedFor,
frontloadData: data,
})
)
);
} catch (err) {
console.log('frontload error?', err);
}
What would you expect to happen with errors in this setup?
Do you happen to have a simple demo site that can be used verify how errors work? I may make one, but if you have one already it would be helpful to rule out app code.
Hi! Thank you for cool library :)
My question is - is it possible to disable running of function passed into frontloadConnect()
on navigating back in browser?
Hello,
I really love how frontload works, its been great for me so far. The scenario of nested frontloaded components that are rendered on the second render has come up. I imagine the server side renderer would need to keep running render until all new frontload functions are resolved instead of just twice.
For example
given url /categories/[seo-category-name]
First render:
Root -> get all categories to map seo names to api friendly ids `api/categories`
Second render renders a new frontloaded component based on first render data
Root
CategoryPage -> get category data `api/categories/[category-id]`
From what I can see, the second render does not call frontload again, so the nested components do not fetch data on a server side render. On normal navigation, it works fine because everything runs on mount.
Curious if you have any thoughts on how this could work? (without changing the API to accommodate data fetching strategies)
Hello, Dave!
You did such a great job in react-frontload
.
I found the link on your repo in this issue and I think you created a very simple and workable solution that can be used now.
I also read your article very carefully and would like to discuss it with you a bit.
Async data fetching on BE is an issue because render function doesn't wait until the promise is resolved and returns a component without data. In order to solve it, react-frontload
basically skips the first render and waits for all promises to be resolved. That works very well!
react-frontload
also prevents the first data loading on FE side in the architecture with SSR.
When server-rendering a component with data, we probably don’t want to re-load the data as soon as the component renders on the client.
Right, we don't need an extra data fetching. However, in this case, after React initialization a user would see a page without data. In order to solve it, in SSR I pass the state object to the window
object so the components on FE have props with data in the first render.
Here is a full example.
I see some problems with this approach:
window.state
objectwindow.state
has a state per endpointI would like to know your opinion about this approach and if you know any better.
P. S. I saw your note in the article:
I left those details out purposefully, as established libraries and patterns exist and react-frontload has no opinion about which you use.
But I'm not sure if you decided to leave this particular question outside react-frontload
lib or you meant something else.
Hi,
In the SSR side, it produces warning:
Warning: componentWillMount has been renamed, and is not recommended for use. See https://fb.me/react-unsafe-component-lifecycles for details.
Please update the following components: FrontloadConnectedComponent
Thanks.
There is possible regression to #4
I have a Parent component that has the state (via useState
hooks) which passes the state setters to the view component. The frontloadFuntion
with make the async call and then use the setters passed as props. This works on the client but is not being executed on the server.
The frontload part of the code looks like this:
const frontloadFn = async ({
locale,
setContentData,
categoryId,
setLoading,
}) => {
setContentData(null);
const payload = await fetchContent(locale, categoryId);
setLoading(false);
setContentData(payload);
};
const ArticleView = frontloadConnect(frontloadFn)(
ArticleViewComponent
);
export { ArticleView };
The provider has no more than this
//... other providers wrap <Frontload/>
<Frontload>
<App />
</Frontload>
Is it possible to map props to the component within frontload itself? Kinda like redux's mapStateFromProps
?
something like:
const frontload = (props) => ({
profile: getProfileAsync(props.username)
})
then the components gets profile
prop automatically
Hello and thanks for this powerful react-frontload library!
I'm wondering how I can implement reload client-side.
My use case is the following. I have one high level hook that retrieves data (SSR and client-side) with useFrontload
. I would like the hook to provide a reload
function for the UI to be able to refresh data when the user click on something.
function myHook() {
const { data } = useFrontload('my-component', async ({ api }) => {
const stuff = await api.getStuff();
return stuff
})
return {
data,
reload, // how to implement this reload function that will fetch data again client-side?
}
}
As far as I understand this is not currently possible because the useEffet
inside useFrontload
only run once, on mount:
Line 474 in a206364
Am I missing something?
Would you accept a PR that exposes a reload function from useFrontload
result? This function would internally increment a useState
counter used as a dependency for the useEffect
, forcing it to run again.
const [forcedReload, setForcedReload] = React.useState<number>(0)
React.useEffect(() => {
// current use effect
}, [forcedReload])
return {
...state,
setData: (fn: (data: T) => T) => {
setState((state) => ({
...state,
data: fn(state.data),
}))
},
reload: () => { // adding this
setForcedReload(state => state +1)
}
}
Let me know if it looks good for you :) Thanks!
Hi
I wanted to work around having to use Redux, by wrapping the frontload connected component with a stateful React component.
Although the components rerender after the data is loaded, there's no data in the props with SSR. It works clientside though.
Any ideas?
Thanks a lot!
I tested this by replacing src/app/routes/profile/index.js from https://github.com/cereallarceny/cra-ssr with
import React, { Component } from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { frontloadConnect } from 'react-frontload';
import Page from '../../components/page';
import { getCurrentProfile, removeCurrentProfile } from '../../../modules/profile';
const frontload = async props => {
const id = +props.match.params.id;
// CHANGE: copied the content of the getCurrentProfile action in here
return new Promise(resolve => {
setTimeout(() => {
let profile;
if (id === 1) {
profile = {
id,
name: 'Pekka Rinne',
// image: pekka,
};
} else {
profile = {
id,
name: 'Viktor Arvidsson',
// image: arvidsson,
};
}
props.setData(profile);
resolve(profile);
}, 3000);
});
// await props.getCurrentProfile(+props.match.params.id);
};
class Profile extends Component {
componentWillUnmount() {
this.props.removeCurrentProfile();
}
shouldComponentUpdate(nextProps) {
if (nextProps.match.params.id !== this.props.match.params.id) {
this.props.getCurrentProfile(+nextProps.match.params.id);
}
return true;
}
render() {
const { name, id, image } = this.props.currentProfile;
console.log(this.props);
return (
<Page
id="profile"
title={name}
description={`This is user profile number ${id}`}
image={image}
>
<p>
<b>Name:</b> {name}
</p>
<p>
<b>ID:</b> {id}
</p>
<img src={image} alt={name} style={{ width: '400px' }} />
</Page>
);
}
}
// CHANGE: removed redux connect + default export
const EnhancedComponent = frontloadConnect(frontload, {
onMount: true,
onUpdate: false,
})(Profile);
// CHANGE: Added this container which is default exported
class ProfileContainer extends React.Component {
constructor(props) {
super(props);
this.state = {
currentProfile: {},
};
}
render() {
// In the server logs I see this component is rendered before the profile is fetched and after, but the "currentProfile" state is empty
console.log('render', this.state.currentProfile);
return (
<EnhancedComponent
{...this.props}
currentProfile={this.state.currentProfile}
setData={data => {
// This logs the correct data between 2 renders
console.log('setting data', data);
this.setState({ currentProfile: data });
}}
/>
);
}
}
export default ProfileContainer;
Upgrading to v2 and curious about how frontloadMeta.pending works. I have noticed that when nothing is returned from the useFrontload function, there is nothing in the frontloadServerRender.data. And if I'm reading this right
Lines 408 to 429 in a206364
Here's an example of a redux thunk that doesn't need to return anything, because it is handled in the redux store.
useFrontload('ArticleListContainer', async () => {
await dispatch(fetchAllArticles());
});
So if nothing is returned, it seems like frontloadMeta.pending
is always true.
By adding a simple return true
useFrontload('ArticleListContainer', async () => {
await dispatch(fetchAllArticles());
return true;
});
frontloadMeta.pending
works as expected.
It seems like the options are to either:
true
in the absence of a returned value (maybe here Line 196 in a206364
What do you think?
Hi,
I think that the frontloadMeta
should return some data about the error and not only error: true
when we do SSR there is a big difrance between HTTP 500 or HTTP 404, especially when talking about google crawl budget.
I tried to find some data about the error and all i front is the error flag.
maybe return an array of errors
where it will hold all the errors in the useFrontload
?
Hello,
Thank you for making such an amazing module to utilize SSR with front-end technologies.
We have been planning to use it for one of our project but having issues with overall consistent server side rendering. We have tried it using two types of redux actions, with direct return its works completely fine but with dispatch based return it gives weird results, sometimes getting data from SSR and sometimes not getting. Please find below reference of code to get more ideas about it.
Note : We have used basic setup from your blog.
Working Method 1 :
export function fetchCategories() {
const request = axios.get('${API_URL}/blog/categories');
return{
type: FETCH_CATEGORIES,
payload: request
};
}
Non Working Method 2 :
export function fetchCategories() {
return function(dispatch) {
return axios.get('${API_URL}/blog/categories')
.then(response => {
dispatch({
type: FETCH_CATEGORIES,
payload: response
});
})
.catch((error) => {
console.log(error);
})
}
}
We have try to research a lot but did not find any solution so hoping to get some help here.
Hi,
I tried to use react-frontload with @loadable/component and react 18, suspense + lazy
but it got an error when doing HydreRoot
for Suspense + Lazy, it got:
https://legacy.reactjs.org/docs/error-decoder.html/?invariant=422
There was an error while hydrating this Suspense boundary. Switched to client rendering.
for @loadable/component, it got:
https://legacy.reactjs.org/docs/error-decoder.html/?invariant=418
Hydration failed because the initial UI does not match what was rendered on the server.
and
https://legacy.reactjs.org/docs/error-decoder.html/?invariant=423
There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.
Is there an example using react-frontload v2 with @loadable/component ?
Thank you very much
Hello,
I have a very odd situation going on where a certain page is refetching (re-frontloading) the data after page load, but only on webkit browsers (safari and chrome). Debugging a bit logging out console.log(frontloadMeta.serverRendered);
I see the server always logs true (3 times), safari/chrome log false always (also 3), and firefox logs true once.
These are redux thunks
const { frontloadMeta } = useFrontload('ContentListContainer', async () => {
console.log('frontloading');
await Promise.all([
dispatch(fetchAllArticles()),
dispatch(fetchOtherVideos()),
dispatch(fetchAllVideos()),
]);
return true;
});
The frontload data is there in the source in all browsers.
window.__FRONTLOAD_DATA__={"ContentListContainer":true}
And generally frontloading works everywhere else as expected. Logging the same thing in other places results in frontloadMeta.serverRendered true everywhere, as you'd expect. Places that use similar redux thunks in Promise.all look fine. Its a real mystery...
Any ideas?
Hello,
before finding this package, i don't have any plan to implement SSR with CRA,
but after reading this medium article
i find out that implementing SSR is not that hard i had imagined, so some diving into react-frontload, some ctrl
+ c
and ctrl
+ v
from this repo ,
static pages is fine, will generate HTML completely, work with curl and js disabled mode.
but in the end of day, major goal, dynamic data is not SSR yet
i disable javascript on browser, and data hang on null
( Loading page )
parent component
import React, { Component } from 'react';
import { frontloadConnect } from 'react-frontload';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
//
import Placeholder from './components/Placeholder';
//
import { fetchApplication, clearApplication } from './services/actions';
const frontload = props => {
console.error('INVOKED');
const { id } = props.match.params;
props.clearApplication();
return props.fetchApplication(id);
};
class Application extends Component {
render () {
const { application} = this.props;
console.log("RENDER");
if (!application) return <Placeholder />;
return (
<section>
// some cool stuff that need application data...
</section>
);
}
}
const mapStateToProps = ({ application: { application } }) => ({ application });
const mapDispatchToProps = dispatch =>
bindActionCreators({ fetchApplication, clearApplication }, dispatch);
export default connect(
mapStateToProps,
mapDispatchToProps
)(frontloadConnect(frontload)(Application));
actions.js
export const FETCH_APPLICATION = 'application/FETCH';
export const CLEAR_APPLICATION = 'application/CLEAR';
export const fetchApplication = appId => async dispatch => {
const res = await axios.get(`${process.env.REACT_APP_API_URL}/applications/${appId}`);
console.log('RESOLVED');
return dispatch({ type: FETCH_APPLICATION, payload: res.data });
};
export const clearApplication = () => ({ type: CLEAR_APPLICATION });
reducer.js
import { FETCH_APPLICATION, CLEAR_APPLICATION } from './actions';
const initialState = {
application: null,
};
export default (state = initialState, action) => {
const { type, payload } = action;
switch (type) {
case FETCH_APPLICATION: {
return { ...state, application: payload };
}
case CLEAR_APPLICATION: {
return { ...state, application: initialState.application };
}
default:
return state;
}
};
and the results : hanging on NULL situation on the server side, promise will not fulfilled
├─ [email protected]
├─ [email protected]
├─ [email protected]
├─ [email protected]
├─ [email protected]
├─ [email protected]
The recent changes were designed to make frontload work with React 16.
In initial testing, everything appeared to work but I have found in practice that there are some issues where some components do run frontload and others appear not to.
I don't have any more details as I'm actively investigating it. I will post more as I find more details and fix it.
Hi, first of all the release of version 2 is great.
We migrated to version 2 and there is a behavior that a little bit off.
If I have a component Comp
that uses useFrontload
with a key
of K1
and its server render, but this component is re-rendered in the client the frontload is executed again although the key
is the same value. why is that?
This triggers an issue in react Warning: React has detected a change in the order of Hooks called
Hi,
I tried to use a React Context as the store for my app but the useContext
hook doesn't work inside the frontload function.
any ideas?
HI!
As I figured out it the only refactoring that I need in order to use react-frontload with SSR is to move everything async from componentDidMount and componentDidUpdate to const fronload
However, how to combine different API actions in one place?
componentDidMount() {
// fetch article from API
this.props.fetchPostByUid('news', this.props.match.params.uid, '*')
}
and many more stuff in
componentDidUpdate(prevProps, prevState) {
// waiting for API response and then set the language of the page
if (this.props.post.item.lang && this.props.language.currentLanguage === null) {
this.props.switchLanguage(this.props.post.item.lang)
}
// waiting for API response and then fetch Related articles by tags
if (this.props.post.item.tags !== prevProps.post.item.tags) {
this.props.fetchPostsByTag(this.props.post.item.tags[0], this.state.moreNewsQuantity)
}
// when user clicked on language selector it will be redirected to article
// written in appropriate language
if ((this.props.language.currentLanguage !== prevProps.language.currentLanguage) && (prevProps.language.currentLanguage !== null)) {
if (this.props.post.item.alternate_languages.length > 0) {
this.props.history.push('/news/' + this.props.post.item.alternate_languages[0].uid)
}
else {
this.setState({modalActive: true})
}
}
// load new data when user click on Related article, otherwise links don't work
if (this.props.location !== prevProps.location) {
this.props.fetchPostByUid('news', this.props.match.params.uid, "*")
}
// when user clicked on More News I fetch more news by tags
if (this.state.moreNewsQuantity !== prevState.moreNewsQuantity) {
this.props.fetchPostsByTag(this.props.post.item.tags[0], this.state.moreNewsQuantity);
}
}
How to deal with all of them? Should I leave something in componentDidUpdate or with SSR it's not going to update ever?
In v1 version of this library there was a prop to disable SSR. It was very useful to me. Is it possible to add it again or can you suggest some other quick and convenient workaround?
Hello!
First of all thank you for this amazing library. We've been using it for a while, since the beginning of the project two-three years ago. Right now we're in the midst of trying to improve the SSR experience and we were trying to move from the renderToString
to the renderToNodeStream
. While the first one works as expected and seems to load all the data and send the HTML correctly down, it seems that the second is not "fetching"/calling the frontload
in our components.
Any ideas as to why that might be or what can we do to solve the issue? Or is it a limitation of the library?
For a little bit of context, we're using:
v1
of FrontloadHello,
I saw an error (tons actually) that seems to be coming from frontload's queue holding on to a frontload function with an error.
The error itself was a classic undefined object property error, roughly
const frontload = (props) => {
...
{
subcategories : [props.subcategory.name]
}
...
};
where props.subcategory
is undefined
. That's expected, and easy to work around.
TypeError: Cannot read property 'name' of undefined
at name (/var/app/current/build/webpack:/src/client/components/SubcategoryProductsGrid/SubcategoryProductsGridContainer.ts:58:33)
at Object.fn (/var/app/current/node_modules/react-frontload/lib/index.js:118:26)
at flushQueues (/var/app/current/node_modules/react-frontload/lib/index.js:77:40)
at /var/app/current/node_modules/react-frontload/lib/index.js:68:12
at map (/var/app/current/node_modules/react-frontload/lib/index.js:52:17)
at flushQueues (/var/app/current/node_modules/react-frontload/lib/index.js:67:47)
at Object.frontloadServerRender (/var/app/current/node_modules/react-frontload/lib/index.js:240:18)
at frontloadServerRender (/var/app/current/build/webpack:/src/server/server.ts:131:7)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)
The very first error came from a subcategory route that would call that (SubcategoryProductsGridContainer.ts)
Where things get strange is that same error came up in every route that had a frontloaded component, routes that never render SubcategoryProductsGridContainer.ts, and would never hit that error were still showing the same name undefined error and the stack showing SubcategoryProductsGridContainer. That's what leads me to think it was somehow stuck in the queue.
I couldn't reproduce it now by visiting a bad url. Everything seems to work as expected.
Taking some wild guesses, I see FRONTLOAD_QUEUES
is defined let FRONTLOAD_QUEUES = []
, which means it would be shared for all server side renders, right? If possible, maybe each server render could start with a new array.
import React from 'react';
import { renderToString } from 'react-dom/server';
import Helmet from 'react-helmet';
import { Provider } from 'react-redux';
import { StaticRouter } from 'react-router';
import { Frontload, frontloadServerRender } from 'react-frontload';
import Loadable from 'react-loadable';
....
.then( ss =>
frontloadServerRender(() => {
renderToString(
<Loadable.Capture report={m => modules.push(m)}>
<Provider store={store}>
<StaticRouter location={req.url} context={context}>
<Frontload isServer>
<App />
</Frontload>
</StaticRouter>
</Provider>
</Loadable.Capture>
);
}
)
)
This works on 1.0.1, but fails on 1.0.5 with:
(node:9936) UnhandledPromiseRejectionWarning: TypeError: asyncResource.runInAsyncScope is not a function
at withAsyncContext ...\web\node_modules\react-frontload\lib\index.js:64:24)
at frontloadServerRender (....\web\node_modules\react-frontload\lib\index.js:274:10)
at ..../web/server/loader.js:209:19
at
at process._tickCallback (internal/process/next_tick.js:188:7)
(node:9936) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
Hello there,
I'm using the example that is referenced on the readme for this library (https://github.com/cereallarceny/cra-ssr/), and my expectation is that if a component is rendered on the server, the frontload should not be called in the client and make the same API calls again. I played with arguments for the functions, but cannot really find a way to make it work? Is my understanding correct on this that if a page is rendered on server, the frontload will not run on the client on that same refresh?
Thank you.
I have to say this package is great! It does pretty much exactly what I want, and it does it well.
However using the onUpdate
option causes my app to crash in several places, because running the function given to frontloadConnect
causes my props to change (which I often need).
My question here is if you would consider adding an option to specify which props should cause a reload. This also allows you to control the amount of function calls, so that the frontload function doesn't run on every little prop change, minimizing requests.
I already implemented this myself, adding an updateProps
option which takes an array of successive object keys, i.e ["foo.bar", "user.id"]
. And it seems to work great. If you like, I'd be happy to submit a pull request!
How to use this code for API call please help -
const frontloadState = createFrontloadState.server({
// inject server impl of api for use in data loading functions.
// might make SQL queries directly instead of making HTTP calls if those
// endpoints are on this same server
context: { api: serverApi }
})
I have recently learned react redux not pro level developer, I am trying to build Server side render app react, I need to show AWS server content on initial state which is I feel really critical using react + redux.
my normal redux app was running fine without frontload but it loads data after the first render happens and shows loading but when I try to connect frontload it start throwing an error:
Cannot set property 'props' of undefined, Well I am sure it's not frontload issue, but I am unable to figure it out. need some help. here my code: https://gist.github.com/amit0shakya/7ffb897571a21122586267bb346f4f2b
Hi,
I guess I have a specific implementation issue but some people might also have similar issue. The frontloadServerRender() calls render twice (first to fill queues then second to get the output) this is causing an issue for me with react-jss SSR (the 2 renders are causing class name conflicts and they generated css from client / server is different because of this duplicate render)
Would it be possible to just pass a boolean to the callback?
frontloadServerRender((dryRun) => { return ReactDomServer.renderToString(....) })
https://github.com/davnicwil/react-frontload/blob/master/src/index.js#L206
render(true)
my personal use for this is here
http://cssinjs.org/react-jss/?v=v8.6.1#react-tree-traversing
What would be the best way to get a React Context Consumer value in the frontload function? Should I just wrap frontloadConnect in a HOC that provides it as a prop?
We use v1 and would remain using it but prefer if we can fix the warning regards using componentWillMount
. Do you intend to fix or will you accept a PR to replace it with componentDidMount
?
Line 193 in c941d89
Thank you for making such an amazing module to help us achieve SSR very efficiently.
Is there any way to run more than one actions in single component/container like below ?
We have tried with below example but its not getting the data for second one. We have tried different combinations but no success yet.
const loadProducts = async props =>
await props.getProducts(props, {start: 0, limit:24}, function(err, result) {});
const loadTotalProducts = async props =>
await props.getTotalProducts(props, {start: 0, limit:24}, function(err, result) {});
class ProductList extends Component {
And connect like below
export default connect(mapStateToProps, { getProducts, getTotalProducts })(
frontloadConnect(loadProducts, loadTotalProducts)(ProductList)
);
Any work around or help will be highly appreciated.
Hi,
First of all, thank you for your work :)
I have been using your package for several months now and I am very satisfied. However, I noticed a few days ago that SSR was no longer working on my project. After hours of research, I finally understood why. In my API call, I recently changed my code to get my API's url dynamically (host, token, protocol) via environment variables. But now when dispatch in the frontload, env var are not loaded and process.env.XXX is empty. So my api call isn't made and SSR doesn't work anymore.
This is extremely annoying for me because I don't want to store these env var in my app for security reasons. Do you have an idea how to solve this problem?
Thank you
Hi,
I'm trying to understand the behaviour of the library.
I understand the SSR process, but after the app is rendered and route is changed and include other components that depends of frontload the lifecycle is render()
and the frontload runs only when componentDidMount
. I think that at this stage the render()
should happen again to re-render the component after the data is retrieved like on the server side.
anything that I misunderstood here?
I've tried to build like mentioned the examples in both client/server side but I receive an promise rejection
error.
Envs:
16.3.2
16.1.0
^1.0.3
The implementation is below:
import React, {Fragment} from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { withRouter } from 'react-router';
import { compose } from 'recompose';
import { frontloadConnect } from 'react-frontload';
import Loading from './loading';
const frontload = async props => await props.getClient();
const Default = props =>
class Default extends Component {
componentWillMount() ...
componentDidMount() ...
render() {
const { loading, notifications } = this.props;
console.log('-- props client: ', this.props);
if (loading) return <Loading />
return (
<HtmlHeaders
{...this.props.client.info.SEO}
image={this.props.client.info.logo}
>
<div>
<h1>Its ok for now.</h1>
</div>
</HtmlHeaders>
);
}
}
const mapStateToProps = ({ app, notifications }) => ({
...app,
notifications
})
const mapDispatchToProps = dispatch =>
bindActionCreators({ ...actions }, dispatch);
export default compose(
withRouter,
connect(mapStateToProps, mapDispatchToProps)
)(
frontloadConnect(frontload, {
onMount: true,
onUpdate: false,
})(Default)
);
The error is below:
(node:30081) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'subscribe' of undefined
at WithTheme.componentWillMount (/home/paneladm/projects/react-jobs/node_modules/styled-components/dist/styled-components.cjs.js:2221:39)
Hello, thanks for frontload!
However, I'm struggling to implement this:
Before frontload my component fetch data in componentDidMount, with this.state.X as a parameter.
// fetch X news articles, where X stored as state = {news_quantity: 5} this.props.fetchNewsForMain('ru', this.state.news_quantity)
when I use frontload implemented before Component it knows 0 about this.state. However, if I define this parameter outside of the Component – I wouldn't be able to control it inside.
So, whats your opinion on that? How to send this parameter to frontload?
I use React Router and have a page with links like /view/1, /view/2. These use the same Frontload-enhanced component. But my frontload function is not run when navigating between pages that use the same component. It does work when navigating to a page that use a different component.
I can see that the component runs componentDidUpdate and props.location.pathname is updated so I don't understand why the frontload function is not run again.
Any ideas what I should do?
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.