Answer the question
In order to leave comments, you need to log in
Why isn't Context.Consumer updated on changes to Context.Provider?
I have a web application that walks to the Movie DB API. The SideBar displays movie search filters, by clicking the search button with the selected parameters (genre, year, etc.) it sends a request to the API. This is how the application looks like (SideBar on the left, Home, in which the Movie is located, on the right): I
use React Context to transfer data.
App.js code (Context.Provider in it):
class App extends Component {
constructor(props) {
super(props);
this.state = {
year: '',
genre: '',
country: '',
allGenres: {},
genreId: '',
filter: this.filter
};
}
filter = (year, country, genre, genreId) => {
this.setState(state => ({
...state,
filter: this.filter
}));
};
render() {
return (
<div className="App">
<header className="App-header">
<MovieContext.Provider value={this.state}>
<Home/>
</MovieContext.Provider>
</header>
</div>
);
}
}
export default (App);
function Home(props) {
return (
<div className={classes.root}>
<SideBar/>
<main>
<Movie/>
</main>
</div>
);
}
export default withStyles({withTheme: true})(Home);
function SideBar(props) {
const [open, setOpen] = useState(true);
const [state, setState] = React.useState({
year: '',
genre: '',
country: '',
allGenres: {},
genreId: ''
});
const handleChange = name => event => {
setState({
...state,
[name]: event.target.value,
});
};
const handleChangeGenre = name => event => {
setState({
...state,
[name]: event.target.value,
genreId: event.target.selectedOptions[0].getAttribute('id')
});
};
var apiKey = "blablabla";
useEffect(() => {
fetch(`url`, {
"method": "GET",
"headers": {
"Accept": "application/json"
}
})
.then(response =>
response.ok ? response : Promise.reject(response)
)
.then(response =>
response.json()
)
.then(json => {
setState(state => ({
...state,
allGenres: json
}));
})
.catch(err => {
console.log(err);
});
}, []);
const genreRender = () => {
var genres = state.allGenres.genres;
if (genres) {
return genres.map((genre, id) => {
return (
<option key={id} id={genre.id} value={genre.name}>{genre.name}</option>
)
});
} else return null;
};
const searchMovie = (filter) => {
var year = state.year;
var genre = state.genre;
var genreId = state.genreId;
var country = state.country;
filter(year, genre, genreId, country);
fetch(`url`, {
"method": "GET",
"headers": {
"Accept": "application/json"
}
})
.then(response =>
response.ok ? response : Promise.reject(response)
)
.then(response =>
response.json()
)
.then(json => {
console.log(json);
})
.catch(err => {
console.log(err);
});
};
return (
<div className={classes.root}>
<AppBar position="fixed">
<Toolbar>
<div className={classes.sectionDesktop}>
<IconButton>
<FavoriteIcon/>
</IconButton>
</div>
</Toolbar>
</AppBar>
<Drawer
open={open}
>
<div className={classes.toolbar}>
<Typography className={classes.title} variant="h6" noWrap>
Filters
</Typography>
</div>
<Divider/>
<FormControl variant="outlined" className={classes.formControl}>
<InputLabel ref={inputLabel} htmlFor="outlined-age-native-simple">
Genre
</InputLabel>
<Select
native
value={state.genre}
onChange={handleChangeGenre('genre')}
labelWidth={labelWidth}
inputProps={{
name: 'genre',
id: 'outlined-age-native-simple',
}}
>
<option value=""/>
{genreRender()}
</Select>
</FormControl>
<MovieContext.Consumer>
{({genre, year, genreId, country, filter}) => (
<FormControl variant="outlined" className={classes.formControl}>
<InputLabel ref={inputLabel} htmlFor="outlined-age-native-simple">Year</InputLabel>
<Select
value={state.year}
onChange={handleChange('year')}
labelWidth={labelWidth}
inputProps={{
name: 'age',
id: 'outlined-age-native-simple',
}}
>
<option value=""/>
<option value={2017}>2017</option>
<option value={2018}>2018</option>
<option value={2019}>2019</option>
</Select>
</FormControl>
)}
</MovieContext.Consumer>
<FormControl variant="outlined" className={classes.formControl}>
<InputLabel ref={inputLabel} htmlFor="outlined-age-native-simple">Country</InputLabel>
<Select
value={state.country}
onChange={handleChange('country')}
labelWidth={labelWidth}
inputProps={{
name: 'age',
id: 'outlined-age-native-simple',
}}
>
<option value=""/>
<option value="USA">USA</option>
<option value="UK">UK</option>
<option value="France">France</option>
</Select>
</FormControl>
<MovieContext.Consumer>
{({genre, year, genreId, country, filter}) => (
<div className={classes.divBtn}>
<Button className={classes.Btn} variant="contained" onClick={() => searchMovie(filter)}>
search
</Button>
</div>
)}
</MovieContext.Consumer>
<Typography className={classes.cr}>Copyright © 2019 KatushkaEsina</Typography>
<Typography className={classes.cr2}>All rights reserved</Typography>
</Drawer>
</div>
);
}
export default withStyles({withTheme: true})(SideBar);
function Movie() {
return <MovieContext.Consumer>
{({genre, year, genreId, country, filter}) => (
<div className={classes.root}>
<Paper className={classes.paper}>
<Grid container spacing={2}>
<Grid item>
<ButtonBase className={classes.image}>
<img className={classes.img} alt="moviePoster" src={logo} style={{width: 120, height: 120}}/>
</ButtonBase>
</Grid>
<Grid item xs={12} sm container>
<Grid item xs container direction="column" spacing={2}>
<Grid item xs>
<Typography gutterBottom variant="subtitle1">
{year || 'Movie name'}
</Typography>
<Typography variant="body2" gutterBottom>
Movie description
</Typography>
<Typography variant="body2" color="textSecondary">
Movie genre
</Typography>
</Grid>
<Grid item>
<Typography variant="body2" style={{ cursor: 'pointer' }}>Snow more info</Typography>
</Grid>
</Grid>
</Grid>
</Grid>
</Paper>
</div>
)}
</MovieContext.Consumer>
}
export default withStyles({withTheme: true})(Movie);
export const MovieContext = React.createContext({
genre: '',
country: '',
year: '',
genreId: '',
filter: (genre, country, year, genreId) => {
this.genre = genre || '';
this.country = country || '';
this.year = year;
this.genreId = genreId || '';
},
});
Answer the question
In order to leave comments, you need to log in
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question