反应对象的本机 setState/useState

Posted

技术标签:

【中文标题】反应对象的本机 setState/useState【英文标题】:React Native setState/useState of an Object 【发布时间】:2021-05-17 15:42:50 【问题描述】:

我是 React Native 的新手,不太了解对象的初始状态以及当我要设置多个属性时更新状态的概念。

错误(编辑#2):

Objects are not valid as a React child (found: object with keys userRole). If you meant to render a collection of children, use an array instead.

App.js

const initialLoginState = 
    userRole: null,
    userId: null,
;

const [user, setUser] = useState(initialLoginState);
const [isReady, setIsReady] = useState(false);

const restoreUser = async () => 
    const user = await authStorage.getUser();
    if (user) setUser(user);
;

if (!isReady) 
    return (
        <AppLoading
            startAsync=restoreUser
            onFinish=() => setIsReady(true)
            onError=console.warn
        />
    );


//render
return (
    <AuthContext.Provider value= user, setUser >
        <NavigationContainer>
            user.userRole ? <ViewTest /> : <AuthNavigator />
        </NavigationContainer>
    </AuthContext.Provider>
);

useAuth 在我收到数据时更新用户:

const logIn = (data, authToken) => 
        setUser((prevState) => (
            userRole: 
                ...prevState.userId, 
                userRole: data.USERROLE,
            ,
        ));
        authStorage.storeToken(data.USERID);
    ;

【问题讨论】:

你能澄清initialise first state的意思吗? 我希望我的状态对象具有上面initialLoginState 中所示的属性,以便我可以使用它来有条件地渲染组件。 将计数器设置为 const [counter, setCounter] = useState(0) 然后 setCounter(counter + 1) 递增时类似的东西,但我需要一个具有属性的对象 是的,我现在把问题修改得更清楚。 您可能想分享更多代码,尤其是user 的来源 【参考方案1】:

在@P.hunter、@Erdenezaya 和@Federkun 的帮助下,我得到了正确的答案。

问题在于状态 init 和 setUser()。

    App.js
    const initialLoginState = 
        userRole: null,
        userId: null,
    ;

    const [user, setUser] = useState(
        initialLoginState,
    );
    const [isReady, setIsReady] = useState(false);

    const restoreUser = async () => 
        const user = await authStorage.getUser();
        if (user) setUser(user);
    ;

    if (!isReady) 
        return (
            <AppLoading
                startAsync=restoreUser
                onFinish=() => setIsReady(true)
                onError=console.warn
            />
        );
    

    //syntax error was found in user.userRole
    return (
        <AuthContext.Provider value= user, setUser >
            <NavigationContainer>
                user.userRole ? <ViewTest /> : <AuthNavigator />
            </NavigationContainer>
        </AuthContext.Provider>
    );
    设置用户的上下文功能必须这样做:
export default useAuth = () => 
    const  user, setUser  = useContext(AuthContext);

    const logIn = (data, authToken) => 

        setUser( ...user, userRole: data.USERROLE );

        authStorage.storeToken(data.USERID);
    ;

    const logOut = () => 
        setUser( ...user, userRole: null );
        authStorage.removeToken();
    ;

    return  user, logIn, logOut ;
;

感谢大家的帮助!

【讨论】:

【参考方案2】:

对象作为 React 子级无效(找到:带有键 userRole 的对象)。如果您打算渲染一组子项,请改用数组。

    <AuthContext.Provider value= user, setUser >  // <---- the problem is here
        <NavigationContainer>
            user.userRole ? <ViewTest /> : <AuthNavigator />
        </NavigationContainer>
    </AuthContext.Provider>

我不确定 AuthContext.Provider 是什么,但它正在尝试将对象(用户)呈现为 html 反应元素,请确保您知道 值的数据类型 该组件的prop。

【讨论】:

上下文提供者的值允许我看到值属性的变化。如果我使用useContext,则可以跨组件访问 setUser。但你是对的,如果我使用不同的值来渲染屏幕,它工作正常......【参考方案3】:

功能组件中不需要 prevState。 user 是你设置新状态之前的 prevState

const logIn = (data, authToken) => 
  setUser(...user, userRole: data.USERROLE);
  authStorage.storeToken(data.USERID);
;

【讨论】:

略有不同的错误,但仍然...Objects are not valid as a React child (found: object with keys 0, 1, userRole). If you meant to render a collection of children, use an array instead. 我认为问题出在您正在渲染的 2 个组件内。你能分享 组件吗? 即使换成不同颜色的View也不是问题。画面不会改变。问题出在上下文中...

以上是关于反应对象的本机 setState/useState的主要内容,如果未能解决你的问题,请参考以下文章

如何将对象添加到反应钩子?

如何在反应钩子中修改我选择的对象?

React的 useState解构赋值怎么理解?

用于获取数据的自定义反应钩子在第二次点击时未提供数据

意外状态更新导致“useState”函数

使用 Redux 进行组件验证