You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用useState触发无效Hook调用错误:违反React Hook规则

解决React Hook调用错误:Error: Invalid hook call. Hooks can only be called inside of the body of a function component.

问题重现

编写Library组件时,尝试在useEffect内的异步函数中调用GetLibraries获取数据,触发了上述Hook调用错误。

原Library组件代码

export default function Library() {

    const [libs, setLibs] = useState([{label: "hello", value: "Hello"}])

    useEffect(() => {
        const FuncLibraries = async () => {
            const data = await GetLibraries()

            // Calling setLibs here, which was defined at the top using the useState() hook

            setLibs(data)
        }

        FuncLibraries()
        console.log(libs)
    }, []);

   return (
        <View>
            <Stack.Screen 
            options={
                {
                    headerStyle: styles.HeaderStyle, 
                    headerTitleStyle: styles.HeaderTextStyle, 
                    headerRight:(() => 
                                        <Dropdown
                                                style={styles.libraryDropDownScroll}
                                                itemContainerStyle={styles.libraryDropDownItem}
                                                containerStyle={styles.libraryDropDownContainer}
                                                data={libs}
                                                labelField="label"
                                                valueField="value"
                                                placeholder='Main'
                                                onChange={item => {}}
                                                renderRightIcon={() => (<Ionicons name="arrow-down" size={20} color={Colors.black} style={styles.closeIconStyle}/>)}
                                                />
                                        
                                    )
                    
                    }
                }/>
            </View>
        );
    };

原GetLibraries函数代码

export default async function GetLibraries () {
    const [libs, setLibs] = useState([]);
    const email = await getItemFor("email");


    useEffect(async () => {
        const { data, error } = await supabase
            .storage
            .from('pdfs')
            .list(`${email}/books`);
        
        if (data != null) {
           const libraries = [];
           for (let x = 0; x < data.length; x ++) {
               libraries.push({label: data[x].name, value: x.toString()})
                };
            
        setLibs(libraries);
    }}, [])

    return(libs)
};

错误原因

GetLibraries是普通异步函数,并非React函数组件或自定义Hook,但在里面直接使用了useState和useEffect钩子,违反了React Hook的核心规则:

  • Hooks只能在函数组件的顶层作用域调用
  • 或者在自定义Hook(命名以use开头)的顶层作用域调用

修正方案

把GetLibraries改成纯异步数据获取函数,移除所有Hook,直接处理并返回数据:

修正后的GetLibraries函数

export default async function GetLibraries () {
    const email = await getItemFor("email");
    const { data, error } = await supabase
        .storage
        .from('pdfs')
        .list(`${email}/books`);
    
    if (data != null) {
       const libraries = [];
       for (let x = 0; x < data.length; x ++) {
           libraries.push({label: data[x].name, value: x.toString()})
       };
       return libraries;
    }
    return []; // 数据为空或出错时返回默认空数组
};

修正后的Library组件

export default function Library() {

    const [libs, setLibs] = useState([{label: "hello", value: "Hello"}])

    useEffect(() => {
        const fetchLibraries = async () => {
            const data = await GetLibraries();
            setLibs(data);
            console.log(data); // 直接打印返回的data,原console.log(libs)会拿到更新前的旧值
        }

        fetchLibraries();
    }, []);

   return (
        <View>
            <Stack.Screen 
            options={{
                headerStyle: styles.HeaderStyle, 
                headerTitleStyle: styles.HeaderTextStyle, 
                headerRight: () => (
                    <Dropdown
                        style={styles.libraryDropDownScroll}
                        itemContainerStyle={styles.libraryDropDownItem}
                        containerStyle={styles.libraryDropDownContainer}
                        data={libs}
                        labelField="label"
                        valueField="value"
                        placeholder='Main'
                        onChange={item => {}}
                        renderRightIcon={() => (<Ionicons name="arrow-down" size={20} color={Colors.black} style={styles.closeIconStyle}/>)}
                    />
                )
            }}/>
        </View>
    );
};

额外说明

  • setLibs是异步操作,原代码中fetchLibraries()后直接调用console.log(libs)会拿到更新前的旧值,建议打印返回的data或添加监听libs变化的useEffect查看更新后的值。
  • 如果需要封装带Hook的逻辑,要遵循自定义Hook规则:命名以use开头,比如useGetLibraries,但本次场景仅需纯数据获取,无需使用Hook。

内容的提问来源于stack exchange,提问作者Anirudh Kuppili

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 21:51:07