简体   繁体   English

如何在ReactJS中使用适当的,可测试的事件处理程序制作可重用组件

[英]How to make a reusable component with proper, testable event handlers in ReactJS

Say you want a React component that "raises a custom event", like this checkbox (here in CoffeeScript): 假设您需要一个“引发自定义事件”的React组件,例如此复选框(在CoffeeScript中,此处):

CustomCheckbox = React.createClass
  displayName: "Checkbox"

  getDefaultProps: -> 
    onCheckedChange: () ->

  render: -> 
    <div className="parent">
        <div className={className} onClick={@onClick}></div>
    </div>

  onClick: -> 
    @props.onCheckedChange(); // call the given event handler directly

Now I want to write a test that uses the component and simulate the event: 现在,我想编写一个使用该组件并模拟事件的测试:

describe 'SomeOtherComponentThatUsesACheckbox', ->
  it "some other component that uses a checkbox handles onCheckedChanged", ->
    isChecked = false
    handler = () -> isChecked = true

    checkbox = ReactTestUtils.renderIntoDocument(
      <CustomCheckbox onCheckedChange={handler} />
    );

    ReactTestUtils.Simulate.checkedChange(checkbox)

    isChecked.should.be.equal true

This won't work. 这行不通。 There's no checkedChange on simulate, and if there was it would only emit an event that no one listens to, as the onCheckedChange handler is not hooked up to anything, but just invoked directly. 在Simulation上没有checkedChange,如果有,它只会发出一个没人听的事件,因为onCheckedChange处理程序不会挂接到任何东西,而只是直接调用。 And maybe it's not supposed to work. 也许它不应该起作用。

But the questions are: 但是问题是:

How do I write the CustomCheckbox so that it raises and subscribes to events in the same way React's own components, like <div> and <a> do? 我该如何编写CustomCheckbox,使其以与React自己的组件(如<div><a>一样)的方式引发和订阅事件?

Can I write the CustomCheckbox so I can use ReactTestUtils to simulate the checkedChanged event? 我可以编写CustomCheckbox以便可以使用ReactTestUtils模拟checkedChanged事件吗?

If not, how is a component using other reusable components supposed to be tested without knowing the internals of the reusable component? 如果不是,在不知道可重用组件内部的情况下,应该如何测试使用其他可重用组件的组件?

UPDATE UPDATE

I've updated the question a tiny bit to be more specific to the problem. 我已对问题进行了一点点更新,以更具体地解决该问题。 I've added a little more complexity to the html generated by the component. 我为组件生成的html增加了一些复杂性。 The problem is more precisely: How can I simulate events without knowing the internals of a complex component? 问题更确切地说是:如何在不了解复杂组件内部的情况下模拟事件?

You're not firing a custom event. 您没有触发自定义事件。 Your event is a click event, and your handler is an onClick handler, so using simulate.click should work. 您的事件是一个click事件,您的处理程序是一个onClick处理程序,因此使用simulate.click应该可以。

If you want to make sure that the checkedChange handler is called when the click event happens, you should pass a mock handler in your test and spy on it. 如果要确保在单击事件发生时调用了checkedChange处理程序,则应在测试中传递一个模拟处理程序并对其进行监视。 I don't know what the syntax would be in coffeescript, but something like this: 我不知道coffeescript中的语法是什么,但是像这样:

describe 'SomeOtherComponentThatUsesACheckbox',
  -> it "some other component that uses a checkbox handles onCheckedChanged", -> isChecked = false
  handler = () -> jasmine.createSpy()
      checkbox = ReactTestUtils.renderIntoDocument(
        <CustomCheckbox onCheckedChange={handler} />
      );
  ReactTestUtils.Simulate.click(checkbox) 
  expect(handler).toHaveBeenCalled();

You can unit test the custom check box component to see that isChecked actually changes too, but its using the onClick event, not another event. 您可以对自定义复选框组件进行单元测试,以查看isChecked实际上也发生了变化,但是使用onClick事件(而不是其他事件)对其进行了更改。

Also, you can pass the handler as an onClick handler in the props, and then its obvious from outside that the click event triggers it. 另外,您可以在道具中将处理程序作为onClick处理程序传递,然后从外部可以明显看出click事件会触发它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM