简体   繁体   中英

Redux - Hooks: Using React Hooks with Redux Hooks, create infinite loop or nothing at all

I know this question has been answered a bunch of times already. I just cannot find the answer that solves my problem, leading me to believe, that I am either stupid or my problem has not been had because it is even more stupid than me. So aside from that, this is my problem:

I am trying to create a functional component that takes some information from a redux state in order to render the correct language labels into a login form.

Let's start with the code:

import React, { useState, useEffect } from "react";
import { Paper, TextField } from "@material-ui/core";
import { changeLanguage } from "../redux/actions";
import { useDispatch, useSelector } from "react-redux";



const Login = () => {
    const dispatch = useDispatch();
    const [language, setLanguage] = useState("de");
    const [strings, setStrings] = useState({});

    useEffect(() => {
        console.log("I have been called", language, strings);
        setLanguage(["de", "en"].includes(navigator.language.split("-")[0]) ? navigator.language.split("-")[0] : "de");
    }, [language]);

    dispatch(changeLanguage(language));
    const str = useSelector(state => state.base.strings.login);
    console.log(str);
    setStrings(str); // <- THIS ONE IS CAUSING THE ERROR
    return (
        <div className={"App"}>
            <Paper>
                <TextField label={strings.username}/><br/>
                <TextField label={strings.password} type={"password"}/>
            </Paper>
        </div>
    );
};

export default Login;

This is what I used to get the app working at all. I realize that setting the strings on every render will cause an infinite loop. That much is clear. However when using this code:

import React, { useState, useEffect } from "react";
import { Paper, TextField } from "@material-ui/core";
import { changeLanguage } from "../redux/actions";
import { useDispatch, useSelector } from "react-redux";



const Login = () => {
    const dispatch = useDispatch();
    const [language, setLanguage] = useState("de");
    const [strings, setStrings] = useState({});

    useEffect(() => {
        console.log("I have been called", language, strings);
        setLanguage(["de", "en"].includes(navigator.language.split("-")[0]) ? navigator.language.split("-")[0] : "de");
        dispatch(changeLanguage(language));
        const str = useSelector(state => state.base.strings.login);
        console.log(str);
        setStrings(str);
    }, [language]);

    return (
        <div className={"App"}>
            <Paper>
                <TextField label={strings.username}/><br/>
                <TextField label={strings.password} type={"password"}/>
            </Paper>
        </div>
    );
};

export default Login;

I get this error:

/src/App/pages/login.js
  Line 17:15:  React Hook "useSelector" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function  react-hooks/rules-of-hooks

Search for the keywords to learn more about each error.

And yes, I do understand what it is telling me but I do believe that useEffect is a React Hook or am I missing something here?

I am simply looking for a way to get this to work. It cannot be that hard because I can make it work with class components no problem.

If the question is stupid, please elaborate on why instead of just voting it down. This would be a lot more helpful in developing and understanding for the matter. I have consulted the docs for two hours and tried a bunch of stuff. Nothing has worked.

Thank you for taking the time!

 useEffect(() => {
        console.log("I have been called", language, strings);
        setLanguage(["de", "en"].includes(navigator.language.split("-")[0]) ? navigator.language.split("-")[0] : "de");
        dispatch(changeLanguage(language));
        const str = useSelector(state => state.base.strings.login);
        console.log(str);
        setStrings(str);
    }, [language]);

You are using one hook inside another.That is not allowed.Only place you can place hooks is inside Functional Component and outside any method.For more info https://reactjs.org/docs/hooks-rules.html

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM