1

I'm working on my first project using React + Redux and am encountering few issues when I try to dispatch a function in the componentDidMount part. I tried to follow the Reddit API example project in the docs but as they use JavaScript and I'm using TypeScript not quite everything is the same.

This is the React component where I'm trying to achieve this:

export class EducationComponent extends Component {
    constructor(props: any) {
        super(props);
    }

    componentDidMount() {
        const { dispatch, getUser } = this.props;
        dispatch(getUser());
    }
    public render() {
        return (
            <Content className="component">
                <Demo/>
            </Content>
        );
    }
}

function mapStateToProps(state: State) {
    const { isLoaded, isFetching, user } = state.userProfile;
    return {
        user,
        isFetching,
        isLoaded
    }
}

export default connect(mapStateToProps)(EducationComponent)
export const Education = (EducationComponent);

I'm receiving following error in the const { dispatch, getUser } = this.props; line:

Error:(16, 17) TS2339: Property 'dispatch' does not exist on type 'Readonly<{}> & Readonly<{ children?: ReactNode; }>'.
Error:(16, 27) TS2339: Property 'getUser' does not exist on type 'Readonly<{}> & Readonly<{ children?: ReactNode; }>'.

The project can be found here if there are any uncertainties: https://github.com/jLemmings/GoCVFrontend

Is this the right way to get this done or are there better options?

Thanks

EDIT with current state:

const {Content} = Layout;

export class EducationComponent extends Component {
    constructor(props: any) {
        super(props);
    }

    componentDidMount() {
        this.props.userAction();
    }
    public render() {
        return (
            <Content className="component">
                <Demo/>
            </Content>
        );
    }
}

const mapDispatchToProps = (dispatch: Dispatch) => bindActionCreators({
    userAction: action.getUser,
}, dispatch);

function mapStateToProps(state: State) {
    const { isLoaded, isFetching, user } = state.userProfile;
    return {
        user,
        isFetching,
        isLoaded
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(EducationComponent)

FINAL EDIT (got it working):

interface MyProps {
    getUser: () => void
}

interface MyState {
    userAction: ThunkAction<Promise<void>, {}, {}, AnyAction>
}

export class EducationComponent extends Component<MyProps, MyState> {
    static defaultProps = {getUser: undefined};

    constructor(props: any) {
        super(props);
    }

    componentDidMount() {
        this.props.getUser()
    }

    public render() {
        return (
            <Content className="component">
                <Demo/>
            </Content>
        );
    }

}

const mapDispatchToProps = (dispatch: ThunkDispatch<{}, {}, any>, ownProps: MyProps) => {
    return {
        getUser: () => {
            dispatch(getUser());
        }
    }
}

function mapStateToProps(state: State) {
    const {isLoaded, isFetching, user} = state.userProfile;
    return {
        user,
        isFetching,
        isLoaded
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(EducationComponent)
In0cenT
  • 481
  • 2
  • 11
  • 25

3 Answers3

2

After looking at your project, you are importing the component like this :

import {Education} from "../pages/Public/Education";

This will import the non connected component that's why you don't have access to dispatch.

You should import the default connected component :

import Education from "../pages/Public/Education";
Mohamed Ramrami
  • 12,026
  • 4
  • 33
  • 49
  • Thanks for your suggestion, I've added the current state of the code as it still isn't working. I just can't access the userAction in the props... – In0cenT Oct 03 '19 at 10:50
  • Are you doing `import {EducationComponent}` , or `import EducationComponent ` ? – Mohamed Ramrami Oct 03 '19 at 10:54
  • Sorry I should have mentioned that I followed your suggestion to import it like this: `import EducationComponent` – In0cenT Oct 03 '19 at 10:57
1

You can do it like this

componentDidMount() {
   this.props.getUser();
}

// mapStateToProps

mapDispatchToProps = (state) => {
   getUser: () => dispatch(getUser()); //Don't forget to import getUser from your action creator
}

export default connect(mapStateToProps, mapDispatchToProps)(EducationComponent)
export const Education = (EducationComponent); // Delete this line no need for this because you're already exporting it as default

Reference: https://react-redux.js.org/using-react-redux/connect-mapdispatch#arguments

fctmolina
  • 196
  • 2
  • 10
  • Thanks for your suggestion, I've added the current state of the code as it still isn't working. I just can't access the userAction in the props... – In0cenT Oct 03 '19 at 10:50
  • You can try writing your mapDispatchToProps like this `const mapDispatchToProps = dispatch => { return { // dispatching actions returned by action creators increment: () => dispatch(increment()), decrement: () => dispatch(decrement()), reset: () => dispatch(reset()) } }` – fctmolina Oct 03 '19 at 11:02
  • Thanks for trying to help but it didn't work. I'm working with TypeScript and not JavaScript so it's a bit harder to follow your guidelines... – In0cenT Oct 03 '19 at 11:09
  • @In0cenT This might solve it https://stackoverflow.com/questions/47561848/property-value-does-not-exist-on-type-readonly since TS doesn't know the type of dispatch – fctmolina Oct 03 '19 at 11:16
0

Do you bind the dispatch method using mapDispatchToProps?

corrado4eyes
  • 283
  • 2
  • 11