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

Next.js中document.getElementById取值与Firebase set报错咨询

问题原因

你遇到的报错有4个核心触发点,和你猜测的null有一定关联但不是根本原因:

  • 首先document.getElementById('userName')返回的是整个input DOM元素对象,不是输入框里的文本值,这个DOM对象挂载了React的内部属性__reactFiber$xxx,属性名带$这类Firebase Realtime Database禁止的特殊字符,你把整个DOM对象往数据库存的时候就会触发key非法的报错。
  • 你的按钮事件写的是onClick={ getValue() },等于组件渲染阶段就会立即执行getValue函数,根本不会等用户点击提交,这时候要么DOM还没挂载完成拿到null,要么用户还没输入内容,自然拿不到有效值。
  • 你调用writeUserData的时候参数传错了:函数定义要接收的第二个参数是用户名文本、第三个是地址字符串,你实际传的是{ userN }、{ address }两个对象,等于要存的数据结构完全不对。
  • 额外问题:直接用document.getElementById操作DOM是React/Next.js里不推荐的反模式,很容易出现时序问题、拿错元素的情况,表单提交也没阻止默认的页面刷新行为。
适配方案

用React推荐的受控组件模式实现就可以完全避开这些问题,不需要手动查询DOM:

  1. 用useState存输入的用户名和地址状态
  2. 给input绑定onChange事件实时同步输入值
  3. 表单用onSubmit事件处理提交,记得调用e.preventDefault()阻止默认刷新
  4. 提交的时候直接拿state里存的值传给数据库写入方法就行

修正后的完整代码参考:

'use client' // Next.js App Router下需要加这个标记为客户端组件
import { useState } from 'react'
import { getDatabase, ref, set } from 'firebase/database'

export default function Username() {
  const [address] = useState('') // 替换成你原本获取address的逻辑即可
  const [userName, setUserName] = useState('')

  function writeUserData(userId, userN, walletAddr) {
    const db = getDatabase()
    const reference = ref(db, 'users/' + userId)
    set(reference, {
      username: userN,
      walletAddress: walletAddr
    })
  }

  function handleSubmit(e) {
    // 阻止表单默认提交刷新页面
    e.preventDefault()
    // 直接拿state里的输入值调用写入方法,无需操作DOM
    writeUserData('id', userName, address)
  }

  return (
    <>
      <div>
        <p className="account-Info">address: {address}</p>
      </div>
      <div id="form">
        <h2 className='user-Create'>Create Username</h2>
        <form id='set-User' onSubmit={handleSubmit}>
          <input 
            id='userName' 
            className='user-Create' 
            type='text' 
            placeholder="username" 
            required 
            minLength='3' 
            maxLength='20' 
            pattern="[a-zA-Z0-9_]+" 
            title='only letters, numbers, and underscores'
            value={userName}
            onChange={(e) => setUserName(e.target.value)}
          />
          <button className='user-Create' type="submit">Link Username</button>
        </form>
      </div>
    </>
  )
}

如果你一定要用原生DOM获取的方式(非常不推荐),至少要修正这几个点:

  • 事件绑定改成onClick={getValue}或者onClick={() => getValue()},不要加括号在渲染阶段直接执行函数
  • 拿到DOM元素后取.value属性才是输入的文本:const userN = document.getElementById('userName').value
  • 调用writeUserData的时候直接传值,不要包裹多余的对象:writeUserData('id', userN, address)
  • 给点击/提交事件加e.preventDefault()阻止默认页面刷新

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 11:15:17