Peter
Peter

Reputation: 407

Component does not rerender but redux state has changed via react hooks

I am currently trying to switch from react-redux connect() hoc to the new hooks api which will be introduced in react-redux 7.1.x.

Some examples are already working but I can't solve the following problem. I have the following redux function:

    export const translate = key => (dispatch, getState) =>
    getState().translations.data[key] || "";

It translates a key into a given language. In my component I am currently calling the function like this:

import React, { Fragment, useCallback } from "react";
import { Button } from "@material-ui/core";

import { useDispatch } from "react-redux";

import { LanguageActions } from "../../redux/actions";

export default function LanguageSwitcher() {
    const dispatch = useDispatch();

    const translateKey = useCallback(
        key => dispatch(LanguageActions.translate(key)),
        []
    );
    const requestCustomLanguage = useCallback(
        requestedLanguage =>
            dispatch(LanguageActions.loadCustomLanguage(requestedLanguage)),
        []
    );

    return (
    <Fragment>
        <Button color="primary" onClick={() => requestCustomLanguage("de")}>
            {translateKey("german")}
        </Button>
        |
        <Button
            color="secondary"
            onClick={() => requestCustomLanguage("en")}
        >
            {translateKey("english")}
        </Button>
    </Fragment>
    );
}

When I click on the button, the redux action (loadCustomLanguage()) is called and I can see the switch of the language file in redux from my redux devtools. I would expect that due to the new contents, my component gets rerenderd and displays the new translation for the buttons.

I am not sure if I understood everything from the 7.1.x docs but I thought I have to use useDispatch() to dispatch actions to redux.

I would appreciate any help. If I should provide examples on how I did it before, let me know. Thanks in advance.

Upvotes: 5

Views: 7323

Answers (1)

Peter
Peter

Reputation: 407

I found out the solution to my problem. You have to use "useSelector" in this case. The component does now look like this:

import React, { Fragment, useCallback } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Button } from "@material-ui/core";

import { LanguageActions } from "../../../../redux/actions";

export default function LanguageSwitcher() {
    const dispatch = useDispatch();

    const requestCustomLanguage = useCallback(
        requestedLanguage =>
            dispatch(LanguageActions.loadCustomLanguage(requestedLanguage)),
        []
    );

    const useTranslations = () =>
        useSelector(state => state.translations.data, []);

    const translations = useTranslations();

    return (
    <Fragment>
        <Button color="primary" onClick={() => requestCustomLanguage("de")}>
            {translations.english}
        </Button>
        |
        <Button
            color="secondary"
            onClick={() => requestCustomLanguage("en")}
        >
            {translations.german}
        </Button>
    </Fragment>
    );
}

Upvotes: 6

Related Questions