Search code examples
reactjsreduxserver-sideredux-thunk

How to access dynamic route parameters when preloading server-side render


I am attempting to render a dynamic route preloaded with data fetched via an async thunk.

I have a static initialAction method in my Components that require preloading, and let them call the actions as needed. Once all actions are done and promises are resolved, I render the route/page.

The question that I have is: how do I reference the route parameters and/or props inside a static function?

Here is the relevant code that will call any initialAction functions that may be required to preload data.

const promises = routes.reduce((promise, route) => {
    if (matchPath(req.url, route) && route.component && route.component.initialAction) {
        promise.push(Promise.resolve(store.dispatch(route.component.initialAction(store))))
    }
    return promise;
}, []);

Promise.all(promises)
.then(() => {
    // Do stuff, render, etc
})

In my component, I have the static initialAction function that will take in the store (from server), and props (from client). One way or the other, the category should be fetched via redux/thunk. As you can see, I'm not passing the dynamic permalink prop when loading via the server because I'm unable to retrieve it.

class Category extends Component {

    static initialAction(store, props) {
        let res = store !== null ? getCategory(REACT_APP_SITE_KEY) : props.getCategory(REACT_APP_SITE_KEY, props.match.params.permalink)
        return res
    }

    componentDidMount(){
        if(isEmpty(this.props.category.categories)){
            Category.initialAction(null, this.props)
        }
    }

    /* ... render, etc */
}

And finally, here are the routes I am using:

import Home from '../components/home/Home'
import Category from '../components/Category'
import Product from '../components/product/Product'
import NotFound from '../components/NotFound'

export default [
    {
        path: "/",
        exact: true,
        component: Home
    },
    {
        path: "/category/:permalink",
        component: Category
    },
    {
        path: "/:category/product/:permalink",
        component: Product
    },
    {
        component: NotFound
    }
]

Not entirely sure I'm even doing this in a "standard" way, but this process works thus far when on a non-dynamic route. However, I have a feeling I'm waaaay off base :)


Solution

  • on the server you have request object and on the client, you have location object. Extract url parameters from these objects after checking current environment.

    const promises = routes.reduce((promise, route) => {
        var props = matchPath(req.url, route);
        if ( obj && route.component && route.component.initialAction) {
            promise.push(Promise.resolve(store.dispatch(route.component.initialAction(store, props))))
        }
        return promise;
    }, []);
    

    now you will get url in initialAction in both desktop and server. you can extract dynamic route params from this