React报错Cannot read properties of null (reading 'style')排查
问题原因
你遇到的null报错有两个直接诱因,还有一个React写法的核心问题:
- 选择器语法写错了:
document.querySelector("no-link-show")是查找<no-link-show>自定义标签,要查class为no-link-show的元素必须加类前缀.,正确写法是document.querySelector(".no-link-show"),少了这个点自然拿不到元素。 - 直接访问
input.value会抛引用错误:现代浏览器不会把带id的DOM元素自动挂到全局作用域,你从来没有定义过input这个变量,这里本身就会先报未定义错误。 - 写法违背React设计原则:在React里直接手动操作DOM修改class、style是反模式,很容易和虚拟DOM的重渲染逻辑冲突。你之前用useEffect报错,基本是违反了Hook调用规则——Hook只能写在组件顶层作用域,不能塞到事件回调、条件判断里。
正确实现
React是状态驱动的框架,所有UI变化都应该通过state控制,不要手动改DOM,参考下面的实现:
import React, { useState } from "react" export default function Form() { // 存输入框内容、错误标记两个状态 const [linkValue, setLinkValue] = useState("") const [isInvalid, setIsInvalid] = useState(false) const urlReg = /^(?:(?:https?|ftp):\/\/)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/\S*)?$/; async function handleSubmit(e) { e.preventDefault() if (urlReg.test(linkValue.trim())) { setIsInvalid(false) const res = await fetch(`https://api.shrtco.de/v2/shorten?url=${encodeURIComponent(linkValue)}`) const data = await res.json() console.log(data) // 这里写短链生成后的后续逻辑 } else { setIsInvalid(true) } } return ( <form id="form" onSubmit={handleSubmit}> <input id="input" type="text" name="link" // 校验不通过时动态加noLink类 className={`input ${isInvalid ? 'noLink' : ''}`} placeholder="Shorten a link here..." value={linkValue} onChange={e => setLinkValue(e.target.value)} /> {/* 动态控制错误提示显示 */} <div className="no-link-show" style={{ display: isInvalid ? 'block' : 'none' }} > Please add a link </div> <button type="submit">Shorten It</button> </form> ) }
额外提一句,你原代码里fetch的参数最好用encodeURIComponent包一下输入值,不然url里带特殊字符(比如&、空格)的时候接口请求会出问题。
如果你非要坚持用原生DOM操作(极度不推荐,React重渲染后很容易出问题),只需要修正选择器、提前获取DOM引用即可:
// 仅作错误演示,不要在实际React项目里这么写 const inputEl = document.getElementById("input") const tipEl = document.querySelector(".no-link-show") // 注意前面的点 if (urlReg.test(inputEl.value)) { // 请求逻辑 } else { inputEl.classList.add('noLink') tipEl.style.display = "block" }
内容的提问来源于stack exchange,提问作者shouldBeHavingFun
相关产品推荐
相关产品推荐

