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

React Native中SelectList下拉框触发Invalid hook call错误求助

问题根源

  1. Invalid hook call错误:你的AddUsersScreen是类组件(继承自Component),但在constructor里使用了React.useState——Hooks只能在函数组件或自定义Hook的顶层作用域调用,类组件完全不支持Hooks,这直接违反了Hook规则。
  2. ReferenceError: setSelected找不到:你在constructor里声明的[selected, setSelected]是局部变量,render函数无法访问该变量,调用时自然会报错。

修复方案(类组件适配,改动最小)

直接用类组件的this.state管理下拉选中值,完全不需要Hooks:

  1. 在类的state中添加选中状态字段;
  2. 修改SelectList的setSelected回调为this.setState更新选中值;
  3. 修正注册逻辑中householdId的赋值,确保选中的家庭ID能存入数据库;
  4. 修复输入框的value绑定笔误,避免输入内容不回显。

修改后的完整代码:

// components/AddUsersScreen.js
import { Component } from 'react';
import * as React from 'react';
import { StyleSheet, Text, View, TextInput, Alert, ActivityIndicator } from 'react-native';
import firebase from '../database/firebaseDb';
//css
import { styles } from "../css/Styles";
//
import CheckBox from '@react-native-community/checkbox'
import SelectDropdown from 'react-native-select-dropdown'

import { SelectList } from 'react-native-dropdown-select-list'

export default class AddUsersScreen extends Component { 
  
  constructor() {
    super();
    this.dbRef = firebase.firestore().collection('users');
    this.firestoreRef = firebase.firestore().collection('household');
    this.state = { 
      displayName : '',
      lastname: '',
      email: '',
      phoneNumber: '',
      password:'',
      householdId : '',
      active : '',
      uid: '',
      roleId : '',
      selected: '' // 新增:存储下拉选中的家庭ID
    }
    // 移除此处的useState调用,类组件禁止使用Hooks
  }

  componentDidMount(){
    this.unsubscribe = this.firestoreRef.onSnapshot(this.getCollection);
  }
  componentWillUnmount(){
    this.unsubscribe();
  }

  getCollection = (querySnapshot) => {
    const householdArr = [];
    querySnapshot.forEach((res) => {
      const {householdName} = res.data();   
      householdArr.push({
        householdId: res.id,
        householdName
      });
    });

    this.setState({
      householdArr,
      isLoading: false,
   });

    const householdOptions = householdArr.map(d => ({
      "key" : d.householdId,
      "value" : d.householdName
    }))
    
    this.setState({selectOptions: householdOptions})
  }
  
  updateInputVal = (val, prop) => {
    const state = this.state;
    state[prop] = val;
    this.setState(state);
  }
  storeUser = () => {
    this.setState({
      isLoading: true,
    });
    this.dbRef.doc(this.userDetails.uid).set({
      displayName : this.userDetails.displayName,
      lastname: this.userDetails.lastname,
      email:this.userDetails.email,
      phoneNumber: this.userDetails.phoneNumber,
      householdId : this.userDetails.householdId, 
      roleId : this.userDetails.roleId,
      active : this.userDetails.active,
      uid: this.userDetails.uid
    }).then((res) => {
      this.setState({
        isLoading: false,
        displayName : '',
        lastname: '',
        email: '',
        phoneNumber: '',
        password:'',
        householdId : '', 
        roleId : '',
        active : '',
        uid: '',
        selected: '' // 重置选中状态
      });
      console.log("added")
    })
    .catch((err) => {
      console.error("Error found: ", err);
      this.setState({
        isLoading: false,
      });
    });
  }
  
  registerUser = () => {
    if(this.state.email === '' || this.state.password === '' || this.state.displayName === '' || this.state.phoneNumber === '') {
      Alert.alert('Enter all details!')
      return;
    }
    if(this.state.password.length < 6){
      Alert.alert('Password should be more than 6 characters!')
      return;
    }
    if(!this.state.selected) {
      Alert.alert('Please select a household!')
      return;
    }
    this.setState({
      isLoading: true
    })
    firebase
    .auth()
    .createUserWithEmailAndPassword(this.state.email, this.state.password)
    .then((res) => {
      res.user.updateProfile({
        displayName: this.state.displayName,
        phoneNumber: this.state.phoneNumber
      })
      console.log('User registered successfully! UID : ' +  res.user.uid)
      this.userDetails = {
        displayName : this.state.displayName,
        lastname: this.state.lastname,
        email:this.state.email,
        phoneNumber: this.state.phoneNumber,
        householdId : this.state.selected, // 绑定选中的家庭ID
        roleId : 2,
        active : 1,
        uid: res.user.uid
      }
      this.storeUser();                
      this.setState({
        isLoading: false,
        displayName : '',
        lastname: '',
        email: '',
        password:'',
        phoneNumber: '',
        householdId : '', 
        roleId : '',
        active : '',
        uid: '',
        selected: ''
      })
    })
    .catch(error => this.setState({ errorMessage: error.message }))      
  }
  render() {
    if(this.state.isLoading){
      return(
        <View style={styles.preloader}>
          <ActivityIndicator size="large" color="#d00"/>
        </View>
      )
    }    
    return (
      <View style={styles.container}>  
        <TextInput
          style={styles.inputStyle}
          placeholder="First Name"
          value={this.state.displayName}
          onChangeText={(val) => this.updateInputVal(val, 'displayName')}
        />
        <TextInput
          style={styles.inputStyle}
          placeholder="Last Name"
          value={this.state.lastname}
          onChangeText={(val) => this.updateInputVal(val, 'lastname')}
        />                
        <TextInput
          style={styles.inputStyle}
          placeholder="Email"
          value={this.state.email}
          onChangeText={(val) => this.updateInputVal(val, 'email')}
        />
        <TextInput
          style={styles.inputStyle}
          placeholder="Phone Number"
          value={this.state.phoneNumber} // 修复笔误:从mobile改为phoneNumber
          onChangeText={(val) => this.updateInputVal(val, 'phoneNumber')}
          maxLength={15}
        /> 
        <TextInput
          style={styles.inputStyle}
          placeholder="Password"
          value={this.state.password}
          onChangeText={(val) => this.updateInputVal(val, 'password')}
          maxLength={15}
          secureTextEntry={true}
        /> 
       <SelectList 
        placeholder='Select Household'
        setSelected={(val) => this.setState({ selected: val })} // 用this.setState更新选中值
        data={this.state.selectOptions} 
        save="key"
        search={false}
        defaultValue={this.state.selected}
    />
      <View style={styles.buttonsContainer}> 
      <Text style={styles.buttons} onPress={() => this.registerUser()}>Add User</Text>
      <Text style={styles.buttons} onPress={() => this.props.navigation.navigate('UserListsScreen')}>Back to Users List</Text>                                 
      </View>
      </View>
    );
  }
}

额外说明

如果想迁移到React现代写法,也可以将类组件改为函数组件,用useState管理状态、useEffect替代生命周期方法,这样就能合法使用Hooks,但整体改动会更大。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 23:25:19