Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Typescript how to setState

I am trying to learn typescript with react and I am pretty confused right now, how will I setState of an interface? My code example:

interface Props {
    children: ReactNode | ReactNode[];
}

export interface IMovie {
    title: string;
    video: boolean;
    poster_path: string;
}

export const MoviesContext = createContext<IMovie[] | undefined>([]);

export const MoviesProvider = ({ children }: Props): JSX.Element => {
    const [movies, setMovies] = useState<IMovie[]>();

    return (
            <MoviesContext.Provider value={[movies, setMovies]}>
                {children}
            </MoviesContext.Provider>
    );
};

The error I get is "Type (ΙΜovie[] | Dispatch> | undefined>> is not assignable to type IMovie[]"

any other suggestions on what to change on my code welcomed. :)

like image 764
Marios G Avatar asked Feb 08 '20 19:02

Marios G


People also ask

How do you define a type of setState in TypeScript?

To Fix define TypeScript type for a setState function when React. Dispatch<React. SetStateAction<string>> not accepted, You should set type of setValue inside IDatePickerProps to: setValue : React. Dispatch<React.

How do I use setState in React?

The setState() Method State can be updated in response to event handlers, server responses, or prop changes. This is done using the setState() method. The setState() method enqueues all of the updates made to the component state and instructs React to re-render the component and its children with the updated state.

How do you use states in TypeScript React?

To type the useState hook as an object in React, use the hook's generic, e.g. const [employee, setEmployee] = useState<{name: string; salary: number}>({name: '',salary: 0}) . The state variable will only accept key-value pairs of the specified type.

How do I set up setState?

Syntax: We can use setState() to change the state of the component directly as well as through an arrow function. Example 1: Updating single attribute. We set up our initial state value inside constructor function and create another function updateState() for updating the state.

What is react usestate in typescript?

TypeScript has a generic definition for React useState according to the TypeScript React documentations. Here, S is a generic type. It accepts an initial state, and the hook can accept the state indicated by S and a setState function of type Dispatch<SetStateAction<S>>.

How does setState work in ReactJS?

The setState() schedule changes to the component’s state object and tells React that the component and its children must rerender with the updated state: // Correct this.setState({name: 'Obaseki Nosa'}); React intentionally waits until all components call setState() in their event handlers before rerendering.

Can I use React hooks with typescript?

React makes it easy to build user interfaces and TypeScript type checks all of the JavaScript to help prevent errors. In this article, we will take a look at how to use the most popular and useful React hook, useState, with TypeScript.

How to change the state of a React component?

Whenever the state changes, React re-renders the component to the browser. Before updating the value of the state, we need to build an initial state setup. Once we are done with it, we use the setState () method to change the state object. It ensures that the component has been updated and calls for re-rendering of the component.


1 Answers

The issue here is the value type that your context is defined with is IMovie, where as the type being passed to your context during rendering is actually an array: [movies, setMovies].

One solution would be to define and use a prop interface with your provider, that carries both the movies state as well as the setter for movies like this:

export interface IMovieProviderProps {
    movies? : IMovie,
    setMovies : (movies:IMovie) => void,
}

This IMovieProviderProps interface would then be used to define the shape of your context value, which would provide the means for accessing the movies state as well as updating it, from outside the provider:

/* Define context with new provider props */
export const MoviesContext = createContext<IMovieProviderProps>(null);

export const MoviesProvider = ({ children }: Props): JSX.Element => {
    const [movies, setMovies] = useState<IMovie>();

    /* Define provider value. Can be done inline, but I've defined
    it here for clarity */
    const providerValue : IMovieProviderProps = {
        movies,
        setMovies
    }

    /* Pass providerValue to provider */
    return (<MoviesContext.Provider value={providerValue}>
        {children}
    </MoviesContext.Provider>);
};

/* Define a hook for this provider, that allows the provided value
to be consumed */
export const useMovies = () => useContext(MoviesContext);

The useMovies hook allows the provider value to be accessed from elsewhere in your project, and can be used like this:

const ExampleComponent = () => {

     /* Imported useMovies hook defined with provider above, and
     extract the movies state, and movies setter base on the shape
     of IMovieProviderProps */
     const { movies, setMovies } = useMovies();

     return <>
     {JSON.stringify(movies)}
     <button onClick={() => setMovies(null)}>Set Movies</button>
     </>
}

A key thing to note now is that the context now exposes an object value with the shape of IMovieProviderProps rather than an array value (as your code may have been expecting).

Hope that helps!

like image 82
Dacre Denny Avatar answered Oct 12 '22 21:10

Dacre Denny