ReactJs: Passing url param to outside functions

I’m working on an Isomorphic react application using redux. I’m having issues passing a url parameter into a function that dispatches a redux action

class SingleMovie extends Component { 
    componentDidMount(){
        console.log(this.props.match.params.id); // i can access the id here
    } 
     ..... 
}

function mapStateToProps(state){
    return {movie:state.movie};
}


function loadData(store, id){  //<--how do i get the id parameter 
    return store.dispatch(fetchMovie(id)); //<--so i can pass it here 
}

export default {
loadData,
component: connect(mapStateToProps,{fetchMovie})(SingleMovie)
};

Don’t know if this might help, but this is my Index.js file. Helps with loading the loadData function.

import 'babel-polyfill'
import express from 'express'
import {matchRoutes} from 'react-router-config'
import Routes from './client/Routes'
import renderer from './helpers/renderer'
import createStore from './helpers/createStore'
//const Body = require('./client/components/Body').default;





const app = express();
app.use(express.static('public'));

app.get('*', (req, res)=>{
	const store = createStore();
	//console.log(matchRoutes(Routes, req.path));	
	const promises = matchRoutes(Routes, req.path).map(({route})=>{
		return route.loadData ? route.loadData(store): null;
	});

	Promise.all(promises).then(()=>{
		res.send(renderer(req,store));
	});




});


app.listen(3000, ()=>{
	console.log('Listening on port 3000');
});

I have absolutely no experience with isomorphic React applications and how they are structured (I assume the export structure and the way loadData() is used is because of isomorphism), so what I’m about to say is just experience with React/Redux apps.

Assuming that you have no problems accessing the id of a movie with this.props.match.params.id in the componentDidMount() method and that there is nothing wrong with the fetchMovie action creator, have you tried something to the changes I made below while debugging? This should work and if it doesn’t then you probably need to start tracing, from the component, to the action creator, then to the reducer, to see where it stops working.

I hope that helps.

EDIT: I originally added mapDispatchToProps() but it should work exactly the same way with the code you have, so I changed the code back to match most of yours, the only additions are those in the componentDidMount() method! Also, are you sure that loadData() has access to the store? Have you tried store.getState() to see if you can access the store?

class SingleMovie extends Component { 
    componentDidMount(){
        console.log(this.props.match.params.id); // i can access the id here

        const { id } = this.props.match.params // Additional statement
        this.props.fetchMovie(id); // Additional statement
    } 
     ..... 
}

function mapStateToProps(state){
    return {movie:state.movie};
}

function loadData(store, id){  //<--how do i get the id parameter 
    return store.dispatch(fetchMovie(id)); //<--so i can pass it here 
}

export default {
    loadData,
    component: connect(mapStateToProps, { fetchMovie })(SingleMovie)
};

Still no luck, but thanks to your insights, I was able to understand more about whats going on in the application. Turns out redux runs on the server and notifies the client side redux. hence state change are in sync. Your solution on the other hand, makes the redux call on the client side, but the whole app has been built to receive state from the server. This application was built around Stephen Grider’s Server Side Rendering With React and Redux

I’d appreciate any more pointers though.

Waaah, in that case I’m pretty sure I can’t help and it looks like a rabbit hole to me. :sweat_smile:

If you are actually following the lesson then I suggest just read watching it again and, if you still can’t find what’s wrong, start from scratch. I vaguely recall that one can ask an instructor questions on Udemy, too.

lol…yeah bro. will do. Thanks :+1:

The return object of the matchRoutes function contains two properties (route, match). You can simply get the desired id out of it and pass it to the loadData function as a second parameter.

const app = express();
app.use(express.static('public'));

app.get('*', (req, res)=>{
	const store = createStore();
	//console.log(matchRoutes(Routes, req.path));	
	const promises = matchRoutes(Routes, req.path).map(({route, match})=>{
		return route.loadData ? route.loadData(store, match.params.id): null;
	});

	Promise.all(promises).then(()=>{
		res.send(renderer(req,store));
	});
});

...
1 Like

gotta confess, I actually gave up on the project, trying server side rendering for the first time and when I hit the road block, I basically threw in the towel. woke up this morning and saw your reply, I dashed to my laptop, spun up my NodeJs servers and Eureka! it worked!

Thanks mahn! to think that 4 months later you’d come and save the day :raised_hands: