首页 > 解决方案 > 有没有更简洁的方法在顶层定义 React Hooks useState?

问题描述

我有一个具有很多状态属性的向导组件。它用于保存大约 5 页内容的状态,然后控制向 api 的提交。

在第一个示例中,我遵守了使用 React Hooks 的第一条规则。

1. 只在顶层调用 Hooks

import React, { useState } from 'react'
import ReactDOM from 'react-dom'

const Wizard = props => {
    const [uuid, setUuid] = useState(props.uuid)
    const [firstName, setFirstName] = useState('')
    const [lastName, setLastName] = useState('')
    const [address1, setAddress1] = useState('')
    const [address2, setAddress2] = useState('')
    const [address3, setAddress3] = useState('')
    const [addressState, setAddressState] = useState('')
    //etc for many  

    return (
        <div>
           {/*
           <Page1 firstName={firstName} secondName={secondName} />
               //...more pages 
           */}
        </div>
    )
}

ReactDOM.render(<Wizard uuid={123} />, document.getElementById('root'))

我认为组件设置有点冗长,所以我想将所有useState调用放在不同的函数中(最终移动到单独的文件)并让它返回stateand setters.

import React from 'react'
import ReactDOM from 'react-dom'

const generateState = props => {
    const [uuid, setUuid] = useState(props.uuid)
    const [firstName, setFirstName] = useState('')
    const [lastName, setLastName] = useState('')
    const [address1, setAddress1] = useState('')
    const [address2, setAddress2] = useState('')
    const [address3, setAddress3] = useState('')
    const [addressState, setAddressState] = useState('')
    //etc for many  

    return {
        state: {
            firstName,
            //etc
        },
        setters: {
            setFirstName,
            //etc
        }
    }
}

const Wizard = props => {

    const {
        state,
        setters
    } = generateState(props)

    return (
        <div>
            {/*
            <Page1 firstName={state.firstName} secondName={state.secondName} />
                //...more pages 
            */}
        </div>
    )
}

ReactDOM.render(<Wizard uuid={123}/>, document.getElementById('root'))

第二个例子违反了第一条规则,如果“这些就是规则!”,我想这很好。我的问题是,是否有一种更简洁的方法来定义useState组件顶部的调用并避免错误:?

React Hook "useState" is called in function "generateState" which is neither a React function component or a custom React Hook function  react-hooks/rules-of-hooks

注意:我希望状态在组件中,而不是在其他地方(即 Redux)

标签: javascriptreactjsreact-hooks

解决方案


你得到的 Lint 错误是因为你没有遵循反应指南来创建自定义钩子而不是命名generateState使用useGenerateStatelinter 错误不会出现。

您在第二部分中所做的是创建自定义钩子,只有当您希望它更清洁时才正确使用仅使用useReducer钩子。

检查这个参考:

https://reactjs.org/docs/hooks-rules.html#eslint-plugin

https://reactjs.org/docs/hooks-custom.html#extracting-a-custom-hook

该案例代码将没有 linter 错误:

import React from 'react';
import ReactDOM from 'react-dom';

const useGenerateState = props => {
    const [uuid, setUuid] = useState(props.uuid)
    const [firstName, setFirstName] = useState('')
    const [lastName, setLastName] = useState('')
    const [address1, setAddress1] = useState('')
    const [address2, setAddress2] = useState('')
    const [address3, setAddress3] = useState('')
    const [addressState, setAddressState] = useState('')
    //etc for many  

    return {
        state: {
            firstName,
            //etc
        },
        setters: {
            setFirstName,
            //etc
        }
    }
}

const Wizard = props => {

    const {
        state,
        setters
    } = useGenerateState(props)

    return (
        <div>
            {/*
            <Page1 firstName={state.firstName} secondName={state.secondName} />
                //...more pages 
            */}
        </div>
    )
}

ReactDOM.render(<Wizard uuid={123}/>, document.getElementById('root'))

推荐阅读