0

I have a project using React, React Router Dom(RRD), Redux and Typescript. RRD is by default passing the match and history props to my child component that I define in the Route component props(see below). Inside my component Redux is also adding two props to my component, a function(getPlaylist) and an object(auth).

Inside my component, when I come to type all of the props, I am having trouble typing match and history.

I've tried the following with no luck:

  • RouteComponentProps with my custom props added
  • importing History from RRD, like so: import { History } from "react-router-dom" and using it as a type (see my code)

My component

import React, { useEffect, useState, useMemo, useLayoutEffect } from "react"
import { connect } from "react-redux"
import PropTypes from "prop-types"
import CreatePlaylist from "../components/playlist/CreatePlaylist"
import { getPlaylist } from "../actions/playlistActions"
import isEmpty from "../utils/isEmpty"
import { Auth, Playlist } from "interfaces"
import { RouteComponentProps } from "react-router"
import { History } from "react-router-dom"

type EditPlaystProps2 = {
    getPlaylist: Function
    playlist: Playlist
    auth: Auth
}

interface EditPlaystProps {
    history: History
    auth: Auth
    getPlaylist: Function
    playlist: Playlist
    match: any
}

function EditPlaylist({
    history,
    auth,
    getPlaylist,
    playlist,
    match,
}: RouteComponentProps<EditPlaystProps2>) {
const [currentPlaylist, setcurrentPlaylist] = useState({})

    useEffect(() => {
        const { isAuthenticated } = auth

        if (!isAuthenticated) {
            history.push("/login")
        }
    }, [auth, history])

    useLayoutEffect(() => {
        getPlaylist(match.params.slug)
    }, [getPlaylist, match.params.slug])

    useMemo(() => {
        const { isAuthenticated } = auth

        if (!isAuthenticated) {
            history.push("/login")
        }
        if (playlist) {
            setcurrentPlaylist(playlist)
        }
    }, [auth, history, setcurrentPlaylist, playlist])

    const editQupplistContent = () => {
        const playlistsHaveLoaded = !isEmpty(currentPlaylist.playlist)

        if (playlistsHaveLoaded) {
            return (
                <CreatePlaylist
                    name={currentPlaylist.playlist.name}
                    slug={currentPlaylist.playlist.slug}
                    id={currentPlaylist.playlist._id}
                    title="Edit playlist"
                    buttonText="Edit playlist"
                />
            )
        }
    }

    return (
        <div>
            <h1>Edit playlist</h1>

            {editQupplistContent()}
        </div>
    )
}

EditPlaylist.propTypes = {
    getPlaylist: PropTypes.func.isRequired,
    playlist: PropTypes.object,
    auth: PropTypes.object.isRequired,
}

const mapStateToProps = (state) => ({
    auth: state.auth,
    playlist: state.playlist,
})

export default connect(mapStateToProps, { getPlaylist })(EditPlaylist)
2
  • 1
    Are you really need connect in funtional components? You can use useHistory hook, if you are need access to history, useSecector for your redux state, etc... Commented Nov 1, 2021 at 8:57
  • I have recently converted this function from a class based one to a function comp and wasn't aware of these hooks. So definitely don't need to use connect, thanks for the heads up. Commented Nov 1, 2021 at 9:07

1 Answer 1

2
type Props = RouteComponentProps & {
  getPlaylist: Function,
  playlist: Playlist,
  auth: Auth,
}

like this?

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.