Reactjs + React Router: How To Reference A Specific Object To Pass Down As Properties?
Solution 1:
This is where a centralized state management tool like redux comes in handy. You could dispatch an action (something like SELECT_CLASS
) that sets the selected class in the store, then read that value from your new component. I'd recommend this approach.
However, there is another way. Each browser history entry has a concept of state
. So, when you navigate to your new route, you can save the selected data in the state for that history entry, then read it when the component renders. It would look something like this:
Save state:
router.push({
to: '/path',
state: class1
});
To read it:
router.location.state
React router docs: https://github.com/ReactTraining/react-router/blob/master/docs/API.md#pushpathorloc
UPDATE: Yay for redux! So first, lets define the action + action creator for this:
exportconstSELECT_CLASS = 'SELECT_CLASS';
exportconstselectClass = (class) => {
return {
type: SELECT_CLASS,
class,
}
};
Now, lets take a look at what the reducer to handle this would look like:
import { SELECT_CLASS } from'/path/to/action'constselectedClass = (
state={},
action
) => {
switch (action.type) {
caseSELECT_CLASS:
return action.class;
default:
returns state;
}
};
Now, assuming you've connected your components via react-redux like this:
// First argument is mapStateToProps, the second is mapDispatchToProps// https://github.com/reactjs/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-optionsexportdefaultconnect((state) => state, { selectClass } )(YourComponent);
This is how you'll set the selected class:
// Wherever you need to navigatefunctioneventHandler(e) {
const { selectClass } = this.props;
selectClass(class1);
router.push('/next/location');
}
And in your next component (which should also be connected, but doesn't require mapDispatchToProps
:
render() {
const { selectedClass } = this.props;
// do what you need with the class.
}
If you need any help setting up react + redux, the docs here are fantastic. If the ES6 syntax I used looks unfamiliar, a good reference are the babel docs here
UPDATE 2: I took your fiddle and ran with it: http://jsfiddle.net/k7wbzc4j/17/. Each button has a click event that will get the correct object.
FINAL UPDATE: So here's the rundown of handleClick
handleClick(e) {
const classTitle = e.target.innerHTML;
let obj = undefined;
data.forEach((schedule) => {
['monday', 'tuesday'].forEach((day) => {
const classes = schedule[day];
returnObject.keys(classes).forEach((c) => {
const cls = classes[c];
if (cls.classTitle === classTitle) {
obj = cls;
}
});
})
});
if (obj) {
// do your navigation here
}
}
First, we use forEach
to iterate over the array data
that holds all of the schedules. Then, we iterate over each day (currently only monday
and tuesday
) to get all the classes on that day for the current schedule. Then, since we don't know the names of all the classes, we just grab all of the keys (which are the class names) and iterate over those. Finally, we can get the actual class objects and check if the classTitle
matched the one that was clicked. If so, we save that object to obj
. At the very end, we ensure that we found a matching object, then do whatever is necessary to properly handle that click. That's pretty messy, but necessary given your data structure. I'd recommend trying to store this data a bit more relationally and storing each type of item separately (eg. Users
, Classes
, Days
, and Schedules
objects all in separate arrays with ids linking them together)
To address your concern that some classTitle
s will be the same, you'll have to also figure out who's schedule was clicked (and potentially the day that it was clicked). You could do this a number of ways: add a data-user
attribute to each button and grab that on click, implement a concept of a "Selected User", create a new component (maybe called UserSchedule
) that renders a row in that table and takes, as props, that user's classes. That way, you'll know that any class that matches belongs to that user. Like I said: a number of ways.
As for showing you how to pass that to a new component, I've demonstrated 2 ways above of how to do that above: through history state or storing the value in a redux reducer and receiving it as props. Doing any more would equate to me solving the entire problem for you, which I'm not going to do since the only way this stuff sticks is for you to do it yourself. Trust in yourself, follow the advice I've given, and use the internet for any specific bugs you're having and you'll come out on top!
Post a Comment for "Reactjs + React Router: How To Reference A Specific Object To Pass Down As Properties?"