Home > Enterprise >  Uncaught Type error after adding context component in react.js
Uncaught Type error after adding context component in react.js

Time:03-31

I have added a new context component MovieContext.js, but it is causing an uncaught type error. I had a look online and it is apparently caused when trying to render multiple children. This I do not understand because as far as I can workout I am only trying to render one.

Error

react-dom.development.js:18747 Uncaught TypeError: render is not a function
    at updateContextConsumer (react-dom.development.js:18747:1)
    at beginWork (react-dom.development.js:19114:1)
    at HTMLUnknownElement.callCallback (react-dom.development.js:3945:1)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:3994:1)
    at invokeGuardedCallback (react-dom.development.js:4056:1)
    at beginWork$1 (react-dom.development.js:23964:1)
    at performUnitOfWork (react-dom.development.js:22776:1)
    at workLoopSync (react-dom.development.js:22707:1)
    at renderRootSync (react-dom.development.js:22670:1)
    at performSyncWorkOnRoot (react-dom.development.js:22293:1)

react_devtools_backend.js:3973 The above error occurred in the <Context.Consumer> component:

    at EventProvider (http://localhost:3000/static/js/bundle.js:4485:5)
    at OptionProvider (http://localhost:3000/static/js/bundle.js:4874:5)
    at UserProvider (http://localhost:3000/static/js/bundle.js:5042:5)
    at AuthProvider (http://localhost:3000/static/js/bundle.js:4303:5)
    at Router (http://localhost:3000/static/js/bundle.js:96142:5)
    at BrowserRouter (http://localhost:3000/static/js/bundle.js:95659:5)
    at App
    at InnerThemeProvider (http://localhost:3000/static/js/bundle.js:37635:70)
    at ThemeProvider (http://localhost:3000/static/js/bundle.js:37342:5)
    at ThemeProvider (http://localhost:3000/static/js/bundle.js:37655:5)

MovieContext.js

import { createContext, useState, useEffect, useContext } from "react";
import jwt_decode from "jwt-decode";
import useFetch from "../hooks/useFetch";
import { useNavigate } from "react-router-dom";
import AuthContext from "./AuthContext";
import EventContext from "./EventContext";

const MovieContext = createContext();

export default MovieContext;

export const MovieProvider = ({ children }) => {
    let { user } = useContext(AuthContext);
    let { trainMeetingRecommendation } = useContext(EventContext)
    let api = useFetch;

    const [movie, setMovie] = useState("");
    const [rating, setRating] = useState({
        user: user.user_id,
        movie: 0,
        score: null,
    });
    const [recommendedMovies, setRecommendedMovies] = useState([]);
    const [watchedMovies, setWatchedMovies] = useState([]);

    // useEffect(() => {
    //  getRecommendedMovies();
    //  getWatchedMovies();
    // }, []);

    let getWatchedMovies = async () => {
        let { response, data } = await api(`/watched_list/`, "GET");
        if (response.status === 200) {
            setWatchedMovies(data);
        }
    };

    let addToWatchedList = async (id) => {
        let { response, data } = await api(`/add_watched_movie/${id}`, "POST", {
            movie: id,
            user: user.user_id,
        });
    };

    let editRating = async (id) => {
        let { response, data } = await api(`/edit_rating/${id}`, "PUT", {
            user: user.user_id,
            movie: id,
            score: rating.score,
        });
        if (response.status === 200) {
            setRating(data);
        } else {
            setRating({ user: user.user_id, movie: id, score: 0.0 });
            console.log(rating.score);
        }
    };

    let getRating = async (id) => {
        let { response, data } = api(`/get_rating/${id}`, "GET");
        if (response.status === 200) {
            setRating(data);
        } else if (response.status === 400) {
            setRating({ user: user.user_id, movie: id, score: 0.0 });
            console.log(rating.score);
        } else {
            setRating({ user: user.user_id, movie: id, score: 0.0 });
            console.log(rating.score);
        }
    };

    let getRecommendedMovies = async () => {
        let { response, data } = api(`/rec_movies/`, "GET");
        if (response.status === 200) {
            setRecommendedMovies(data);
        } else {
            alert("Something went wrong");
        }
    };

    let trainMovieRecommendation = async () => {
        let { response, data } = api(`/train/movie/`, "GET");
    };

    let AddRating = async (id, ratingScore) => {
        let { response, data } = await api(`/add_rating/${id}`, "POST", {
            user: user.user_id,
            movie: id,
            score: ratingScore,
        });
        if (response.status === 200) {
            setRating(data);
        }
        trainMovieRecommendation();
        trainMeetingRecommendation();
    };

    let contextData = {
        movie: movie,
        rating: rating,
        recommendedMovies: recommendedMovies,
        watchedMovies: watchedMovies,

        setMovie: setMovie,
        setRating: setRating,
        setRecommendedMovies: setRecommendedMovies,
        setWatchedMovies: setWatchedMovies,
        getWatchedMovies: getWatchedMovies,
        addToWatchedList: addToWatchedList,
        getRating: getRating,
        editRating: editRating,
        getRecommendedMovies: getRecommendedMovies,
        AddRating: AddRating,
    };

    return (
        <MovieContext.Provider value={contextData}>
            {children}
        </MovieContext.Provider>
    );
};

Movies.js

import React, { useState, useContext, useEffect } from "react";
import {
    Tooltip,
    IconButton,
    Box,
    Collapse,
    TextField,
    Grid,
    Typography,
    Rating,
    Stack,
    ListItem,
} from "@mui/material";
import Card from "@mui/material/Card";
import CardHeader from "@mui/material/CardHeader";
import CardMedia from "@mui/material/CardMedia";
import { moviesWithPoster } from "../data/DummyMoviesData";
import SearchIcon from "@mui/icons-material/Search";
import CloseIcon from "@mui/icons-material/Close";
import "../../styling/pages/Movies.css";
import moviePoster from "../../styling/images/empty_movie_poster.png";
import MovieContext from "../../components/helper/context/MovieContext";
import FormButton from "../../components/FormButton";
import HomePageTitle from "../../components/HomePageTitle";
import TextButton from "../../components/TextButton";

const Movies = () => {
    let {
        movie,
        rating,
        recommendedMovies,
        watchedMovies,
        setMovie,
        setRating,
        setRecommendedMovies,
        setWatchedMovies,
        getWatchedMovies,
        addToWatchedList,
        getRating,
        getRecommendedMovies,
        AddRating,
    } = useContext(MovieContext);
    const [openSearch, setOpenSearch] = React.useState(false);

    const toggleSearch = () => {
        setOpenSearch(!openSearch);
    };

    const openSearchCollapse = () => {
        setOpenSearch(true);
    };

    const [searchValue, setSearchValue] = useState("");

    return (
        <>
            <HomePageTitle title={"movies"} />

            <Grid
                container
                justifyContent={"center"}
                alignItems={"flex-start"}
                spacing={2}
                padding={2}
            >
                <Grid item xs={12}>
                    <TextField
                        label={"search"}
                        fullWidth
                        value={searchValue}
                        placeholder={"search for a movie"}
                        onChange={(event) => {
                            setSearchValue(event.target.value);
                        }}
                        InputProps={{
                            endAdornment: (
                                <TextButton
                                    text={openSearch ? "close" : "open"}
                                    onClick={toggleSearch}
                                />
                            ),
                        }}
                    />
                </Grid>
                <Grid item xs={12}>
                    <Collapse in={openSearch}>
                        <div className={"home-page-card-background"}>
                            <Grid container direction={"row"} padding={2} spacing={2}>
                                <Grid item xs={12}>
                                    <h5 className={"home-page-card-title"}>search result</h5>
                                </Grid>
                                <Grid item xs={12}>
                                    <Grid
                                        container
                                        direction={"row"}
                                        spacing={2}
                                        alignItems={"center"}
                                    >
                                        {/* LIST OF ALL MOVIES */}
                                        {moviesWithPoster
                                            .filter((movie) => {
                                                if (
                                                    movie.title
                                                        .toLowerCase()
                                                        .includes(searchValue.toLowerCase())
                                                ) {
                                                    return movie;
                                                }
                                            })
                                            .map((movie) => {
                                                return (
                                                    <Grid item>
                                                        <Card sx={{ width: 180 }}>
                                                            <CardMedia
                                                                component="img"
                                                                image={moviePoster}
                                                                alt={movie.title}
                                                            />

                                                            <Stack
                                                                spacing={1}
                                                                padding={1}
                                                                alignItems={"center"}
                                                            >
                                                                <Rating
                                                                    name="simple-controlled"
                                                                    sx={{ fontSize: "1.2em" }}
                                                                    precision={0.5}
                                                                    max={5}
                                                                    // onChange={(event, newValue) => (this.setState({score: newValue, onChange: this.fetchAddRating(movie.id)}))}
                                                                />

                                                                <Tooltip
                                                                    title={movie.title}
                                                                    placement="top-start"
                                                                >
                                                                    <Typography noWrap>{movie.title}</Typography>
                                                                </Tooltip>

                                                                <FormButton text={"watch"} />
                                                            </Stack>
                                                        </Card>
                                                    </Grid>
                                                );
                                            })}
                                    </Grid>
                                </Grid>
                            </Grid>
                        </div>
                    </Collapse>
                </Grid>

                <Grid item xs={12}>
                    <div className={"home-page-card-background"}>
                        <Grid container direction={"row"} padding={2} spacing={2}>
                            <Grid item xs={12}>
                                <h5 className={"home-page-card-title"}>club movies</h5>
                            </Grid>

                            <Grid item xs={12}>
                                <Stack direction={"row"} overflow={"auto"}>
                                    {moviesWithPoster.map((movie) => {
                                        return (
                                            <ListItem sx={{ p: 1 }}>
                                                <Card sx={{ width: 150 }}>
                                                    <CardMedia
                                                        component="img"
                                                        sx={{ height: "100%" }}
                                                        image={moviePoster}
                                                        alt={movie.title}
                                                    />

                                                    <Stack spacing={1} padding={1} alignItems={"center"}>
                                                        <Rating
                                                            name="simple-controlled"
                                                            sx={{ fontSize: "1.2em" }}
                                                            precision={0.5}
                                                            max={5}
                                                            // onChange={(event, newValue) => (this.setState({score: newValue, onChange: this.fetchAddRating(movie.id)}))}
                                                        />

                                                        <Tooltip title={movie.title} placement="top-start">
                                                            <Typography noWrap>{movie.title}</Typography>
                                                        </Tooltip>
                                                        <FormButton text={"watch"} />
                                                    </Stack>
                                                </Card>
                                            </ListItem>
                                        );
                                    })}
                                </Stack>
                            </Grid>
                        </Grid>
                    </div>
                </Grid>
                <Grid item xs={12}>
                    <div className={"home-page-card-background"}>
                        <Grid container direction={"row"} padding={2} spacing={2}>
                            <Grid item xs={12}>
                                <h5 className={"home-page-card-title"}>recommended</h5>
                            </Grid>
                            <Grid item xs={12}>
                                <Stack direction={"row"} overflow={"auto"}>
                                    {recommendedMovies.map((movie) => {
                                        return (
                                            <ListItem sx={{ p: 1 }}>
                                                <Card sx={{ width: 150 }}>
                                                    <CardMedia
                                                        component="img"
                                                        sx={{ height: "100%" }}
                                                        image={moviePoster}
                                                        alt={movie.title}
                                                    />
                                                    <Stack spacing={1} padding={1} alignItems={"center"}>
                                                        <Rating
                                                            name="simple-controlled"
                                                            sx={{ fontSize: "1.2em" }}
                                                            precision={0.5}
                                                            max={5}
                                                            onChange={(event, newValue) =>
                                                                setRating({
                                                                    score: newValue,
                                                                    onChange: AddRating(movie.id, newValue),
                                                                })
                                                            }
                                                        />
                                                        <Tooltip title={movie.title} placement="top-start">
                                                            <Typography noWrap>{movie.title}</Typography>
                                                        </Tooltip>
                                                        <FormButton
                                                            text={"watch"}
                                                            onClick={() => {
                                                                addToWatchedList(movie.id);
                                                            }}
                                                            onChange={() => {
                                                                getRecommendedMovies();
                                                            }}
                                                        />
                                                    </Stack>
                                                </Card>
                                            </ListItem>
                                        );
                                    })}
                                </Stack>
                            </Grid>
                        </Grid>
                    </div>
                </Grid>
                <Grid item xs={12}>
                    <div className={"home-page-card-background"}>
                        <Grid container direction={"row"} padding={2} spacing={2}>
                            <Grid item xs={12}>
                                <h5 className={"home-page-card-title"}>watched</h5>
                            </Grid>

                            <Grid item xs={12}>
                                <Stack direction={"row"} overflow={"auto"}>
                                    {watchedMovies.map((movie) => {
                                        return (
                                            <ListItem sx={{ p: 1 }}>
                                                <Card sx={{ width: 150 }}>
                                                    <CardMedia
                                                        component="img"
                                                        sx={{ height: "100%" }}
                                                        image={moviePoster}
                                                        alt={movie.title}
                                                    />

                                                    <Stack spacing={1} padding={1} alignItems={"center"}>
                                                        <Rating
                                                            name="simple-controlled"
                                                            sx={{ fontSize: "1.2em" }}
                                                            precision={0.5}
                                                            max={5}
                                                            // onChange={(event, newValue) => (this.setState({score: newValue, onChange: this.fetchAddRating(movie.id)}))}
                                                        />

                                                        <Tooltip title={movie.title} placement="top-start">
                                                            <Typography noWrap>{movie.title}</Typography>
                                                        </Tooltip>

                                                        <FormButton text={"watch"} />
                                                    </Stack>
                                                </Card>
                                            </ListItem>
                                        );
                                    })}
                                </Stack>
                            </Grid>
                        </Grid>
                    </div>
                </Grid>
            </Grid>
        </>
    );
};

export default Movies;

App.js

import React, { useEffect, useContext } from "react";
import "../../styling/pages/App.css";
import Navbar from "../../components/root/Navbar";
import HomePage from "../root/Homepage";
import LogIn from "../root/Login";
import Logout from "../root/Logout";
import NotFound404 from "../root/NotFound";
import Profile from "../home/Profile";
import {
    useLocation,
    BrowserRouter as Router,
    Routes,
    Route,
} from "react-router-dom";
import Signup from "../root/Signup";
import HomeRouter from "./HomeRouter";
import Clubs from "../home/Clubs";
import Movies from "../home/Movies";
import Options from "../home/Options";
import Home from "../home/Home";
import OthersProfile from "../../components/OthersProfile";
import PrivateRoute from "../../components/helper/PrivateRoute";
import { AuthProvider } from "../../components/helper/context/AuthContext";
import { UserProvider } from "../../components/helper/context/UserContext";
import ClubDetail from "../../components/ClubDetail";
import NewClub from "../../components/NewClubForm";
import Discussion from "../home/Discussion";
import NewEvent from "../../components/NewEventForm";
import ClubDiscussion from "../../components/ClubDiscussion";
import ShowEvent from "../../components/ShowEvent";
import { OptionProvider } from "../../components/helper/context/OptionContext";
import { EventProvider } from "../../components/helper/context/EventContext";
import MovieProvider from "../../components/helper/context/MovieContext";

function App() {
    return (
        <Router>
            <AuthProvider>
                <UserProvider>
                    <OptionProvider>
                        <EventProvider>
                            <MovieProvider>
                                <Navbar />
                                <Routes>
                                    <Route path={"/"} element={<HomePage />} />
                                    <Route path={"/login"} element={<LogIn />} />
                                    <Route path={"/signup"} element={<Signup />} />
                                    <Route path={"/logout"} element={<Logout />} />
                                    <Route
                                        path={"/home"}
                                        element={
                                            <PrivateRoute>
                                                <HomeRouter />
                                            </PrivateRoute>
                                        }
                                    >
                                        <Route index element={<Home />} />
                                        <Route path={"logout"} element={<Logout />} />
                                        <Route path={"profile"} element={<Profile />} />
                                        <Route path={"movies"} element={<Movies />} />
                                        <Route path={"clubs"} element={<Clubs />}>
                                            <Route path={":clubID"} element={<ClubDetail />}>
                                                <Route path={":userID"} element={<OthersProfile />} />
                                            </Route>
                                            <Route path={"clubs/new"} element={<NewClub />} />
                                        </Route>
                                        <Route path={"discussion"} element={<Discussion />}>
                                            <Route path={":clubID"} element={<ClubDiscussion />}>
                                                <Route index element={<ShowEvent />} />
                                                <Route path={"new"} element={<NewEvent />} />
                                            </Route>
                                        </Route>
                                        <Route path={"options"} element={<Options />} />
                                    </Route>
                                    <Route path={"*"} element={<NotFound404 />} />
                                </Routes>
                            </MovieProvider>
                        </EventProvider>
                    </OptionProvider>
                </UserProvider>
            </AuthProvider>
        </Router>
    );
}

export default App;

Any help would be much appreciated.

CodePudding user response:

You have a named export for MovieProvider and in the same file a default export for MovieContext;

export default MovieContext; // default export

export const MovieProvider // named export

In App.js you are using a default import and thus importing the MovieContext instead of the Provider.

import MovieProvider from "../../components/helper/context/MovieContext"; // default import will import MovieContext with the variable name MovieProvider 

To use the named import change this :

import MovieProvider from "../../components/helper/context/MovieContext";

to this:

import {MovieProvider} from "../../components/helper/context/MovieContext";
  • Related