使用Enzyme.js模拟输入变更时状态更新错误的求助
问题根源与解决方案
嘿,我一眼就瞅出问题所在了!你的state里出现undefined字段,是因为事件处理逻辑和测试模拟的事件属性不匹配,具体来说:
问题分析
- 你的
updateSubmission函数里,是通过event.target.id来定位要更新的字段:
updateSubmission(event) { let updatedSubmission = Object.assign({}, this.state.submission); updatedSubmission[event.target.id] = event.target.value; // 这里依赖event.target.id this.setState({ submission: updatedSubmission }); }
- 但在测试代码里,你模拟
change事件时,给的target对象只传了name和value,没有传id:
wrapper.find('#firstName').simulate( 'change', { target: { name: 'firstName', value: 'John' } } // 缺少id属性 )
这就导致event.target.id在测试中取不到值,变成了undefined,所以updatedSubmission[undefined] = 'John',最终state里就多了个键为undefined的字段。
另外,你的实际input标签也只设置了id,没有name属性——虽然真实场景下用户输入时event.target.id能拿到值,但测试模拟时没传就会出问题。
两种解决方案
方案一:修改测试代码,传递正确的id属性
直接在模拟事件的target里加上id,和input的id保持一致:
it('should respond to change event and change the state of the Component', () =>{ const wrapper = shallow(<ApplicationForm/>); console.log(wrapper.find('#firstName').debug()); wrapper.find('#firstName').simulate( 'change', { target: { id: 'firstName', value: 'John' } } // 补充id属性 ) expect(wrapper.state().submission.firstName).to.equal('John'); })
方案二:统一使用name属性(推荐,更符合React表单最佳实践)
这种方式更通用,也是React处理表单输入的常规做法:
- 给input标签添加
name属性,和id保持一致:
<input type="text" id="firstName" name="firstName" <!-- 添加name属性 --> className="form-control form-control-sm" placeholder="First name" onChange={this.updateSubmission.bind(this)} />
- 修改
updateSubmission函数,改用event.target.name来定位字段:
updateSubmission(event) { const { name, value } = event.target; // 解构name属性 let updatedSubmission = Object.assign({}, this.state.submission); updatedSubmission[name] = value; this.setState({ submission: updatedSubmission }); }
这样你的原有测试代码就不需要修改了,而且后续添加其他表单字段时,逻辑可以直接复用,扩展性更好。
验证效果
不管用哪种方案,修改后再运行测试,state.submission.firstName都会正确更新为'John',不会再出现undefined的字段啦!
内容的提问来源于stack exchange,提问作者Maciej Ziolkowski
相关产品推荐
相关产品推荐

