I'm trying use context api with react-router. I have a container which has a list of songs in its trackList prop from mapStateToProps and I want to pass that to a stateless component called TrackDetail using context api (no react-redux). As you'll see below I've used both the useContext hook and the render props pattern without sucess to get that value from context.
This is what I have in the Routes file:
import React, { Component } from "react";
import { BrowserRouter as Router, Route, Switch, Redirect } from "react-router-dom";
import TrackList from "../../containers/TrackList/TrackList";
import TrackDetail from "../TrackDetail/TrackDetail";
class Routes extends Component {
render() {
return (
<div className="Routes">
<Router>
<Switch>
{this.props.children}
<Route path="/tracks" component={TrackList} exact />
<Route path="/tracks/:id" component={TrackDetail} exact/>
<Route exact path="/" render={() => (<Redirect to="/tracks" />)} />
<Route path="*" render={() => (<Redirect to="/tracks" />)} />
</Switch>
</Router>
</div>
);
}
}
export default Routes;
This is my TrackList.jsx container (connected to redux):
import React, { Component } from "react";
import { connect } from "react-redux";
import "./TrackList.scss";
import Spinner from "../../components/shared/Spinner/Spinner";
export const TrackListContext = React.createContext();
class TrackListProvider extends Component {
state = {
foo: "bar"
}
render() {
return (
<TrackListContext.Provider value={this.state}>
{this.props.children}
</TrackListContext.Provider>
)
}
};
export class UnConnectedTrackList extends Component {
constructor(props) {
super(props);
this.state = {
value: ""
};
}
componentDidMount() {
if (this.props.trackList.length === 0) {
this.props.getTracks()
.then(()=>this.props.changeSpinnerState());
}
}
render() {
if (this.props.spinnerState) return <Spinner />;
return <TrackListProvider trackList={this.props.trackList}>
<div>
more content
</div>
</TrackListProvider>;
}
}
const mapStateToProps = state => {
const trackList = state.trackList.length !== 0 ? state.trackList : [];
return {
trackList,
};
};
export default connect(
mapStateToProps,
null
)(UnConnectedTrackList);
And this is my TrackDetail.jsx:
import React, { useContext } from "react";
import {TrackListContext} from '../../containers/TrackList/TrackList';
import "./TrackDetail.scss";
const TrackDetailCmp = (props) => {
const value = useContext(TrackListContext);
// value is undefined
const currentTrackIndex = 0;
const { trackList} = props;
// trackList is undefined
return (
<div className="container">
<h3></h3>
</div>
);
};
const withContext = (Component) => {
return (props) => <TrackListContext.Consumer>
{(value) => <Component {...props} trackList={value} />}
</TrackListContext.Consumer>
};
const TrackDetail = withContext(TrackDetailCmp);
export default TrackDetail;
But I'm getting undefined.
Maybe is an issue with the versions.
This is my package.json:
{
"dependencies": {
"react": "^16.9.0",
"react-dom": "^16.9.0",
"react-redux": "^7.1.0",
"react-router": "^5.0.1",
"react-router-dom": "^5.0.0",
"redux": "^4.0.4",
"redux-thunk": "^2.3.0"
},
"devDependencies": {
"@types/jest": "^24.0.17",
"@types/react": "^16.9.2",
"enzyme": "^3.10.0",
"enzyme-adapter-react-16": "^1.14.0",
"node-sass": "^4.12.0"
}
}