props变更时,如何通过类方法重新渲染React函数组件?
问题分析
你的核心问题在于:Validator实例被存在父组件的useState中,其引用从未改变。当点击按钮调用isOk()修改实例内部的#showMessage和#error时,React因为检测不到validator props的引用变化,不会触发ValidatedInput组件的重新渲染,因此错误消息无法即时显示。
React组件的重新渲染触发条件是props/state的引用或值发生变化,而你的Validator是一个自定义类实例,内部属性的修改不会改变实例本身的引用,所以ValidatedInput的useEffect依赖项[value, validator]不会触发更新。
解决方案
下面提供两种符合React状态管理逻辑的修复方案:
方案一:将Validator的状态迁移到React State中
把原本存在Validator实例内部的error和showMessage放到React的state里,让状态变化直接触发组件渲染:
// 重构Validator为纯函数工具类,不再维护内部状态 export default class Validator { validate = (value) => { // 这里写你的验证逻辑 return value ? "" : "ERROR: 输入不能为空"; }; isOk = (error) => { return error.length === 0; }; } export const ValidatedInput = (props) => { const { value, onChange, error, showMessage } = props; return ( <> <input value={value} onChange={(e) => onChange(e.target.value)} /> {showMessage && <label style={{ color: 'red' }}>{error}</label>} </> ); }; export const ValidatedInputDemo = () => { const [value, setValue] = useState(""); const [error, setError] = useState(""); const [showMessage, setShowMessage] = useState(false); const validator = new Validator(); const handleCheck = () => { const currentError = validator.validate(value); setError(currentError); setShowMessage(true); validator.isOk(currentError) ? alert("OK") : alert("BAD"); }; return ( <> <ValidatedInput value={value} onChange={setValue} error={error} showMessage={showMessage} /> <br /> <button onClick={handleCheck}>Check</button> </> ); };
方案二:让Validator支持状态回调,通知组件更新
如果需要保留Validator类的内部状态,可以给它添加回调函数,当内部状态变化时通知组件更新:
export default class Validator { #error = ""; #showMessage = false; #onChangeCallback = null; // 添加注册回调的方法 subscribe(callback) { this.#onChangeCallback = callback; } #notifyChange() { if (this.#onChangeCallback) { this.#onChangeCallback({ error: this.#error, showMessage: this.#showMessage }); } } get error(){ return this.#error; } set error(error){ this.#error = error; this.#notifyChange(); // 状态变化时通知组件 } get showMessage() { return this.#showMessage; } set showMessage(show) { this.#showMessage = show; this.#notifyChange(); // 状态变化时通知组件 } validate = (value) => { this.#error = "ERROR " + value; this.#notifyChange(); return this.#error; }; isOk = () => { this.#showMessage = true; this.#notifyChange(); return this.#error.length === 0 || this.#error ===''; }; } export const ValidatedInput = (props) => { const { value, validator, onChange } = props; const [errorMessage, setErrorMessage] = useState(""); const [showMessage, setShowMessage] = useState(false); useEffect(() => { if (validator) { // 订阅Validator的状态变化 validator.subscribe((state) => { setErrorMessage(state.error); setShowMessage(state.showMessage); }); // 初始化状态 const error = validator.validate(value); setErrorMessage(error); setShowMessage(validator.showMessage); } }, [validator, value]); return ( <> <input value={value} onChange={(e) => onChange(e.target.value)} /> {showMessage && <label style={{ color: 'red' }}>{errorMessage}</label>} </> ); }; export const ValidatedInputDemo = () => { const [value, setValue] = useState(""); const [validator] = useState(new Validator()); return ( <> <ValidatedInput value={value} validator={validator} onChange={setValue} /> <br /> <button onClick={() => { validator.isOk() ? alert("OK") : alert("BAD"); }} > Check </button> </> ); };
关键说明
- 方案一更贴合React的状态管理理念,把UI相关的状态交给React State管理,Validator只负责纯验证逻辑,职责更清晰。
- 方案二保留了Validator类的内部状态,通过订阅回调的方式让组件感知状态变化,适合需要复用Validator实例状态的场景。
内容的提问来源于stack exchange,提问作者John Taylor
相关产品推荐
相关产品推荐

