Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test a prop update on React component

What is the correct way of unit testing a React component prop update.

Here is my test fixture;

describe('updating the value', function(){         var component;         beforeEach(function(){             component = TestUtils.renderIntoDocument(<MyComponent value={true} />);         });          it('should update the state of the component when the value prop is changed', function(){             // Act             component.props.value = false;             component.forceUpdate();             // Assert             expect(component.state.value).toBe(false);         }); }); 

This works fine and the test passes, however this displays a react warning message

'Warning: Dont set .props.value of the React component <exports />. Instead specify the correct value when initially creating the element or use React.cloneElement to make a new element with updated props.' 

All i want to test is the update of a property, not to create a new instance of the element with a different property. Is there a better way to do this property update?

like image 511
Win Avatar asked Jun 03 '15 08:06

Win


People also ask

Can we update the props in React component?

A component cannot update its own props unless they are arrays or objects (having a component update its own props even if possible is an anti-pattern), but can update its state and the props of its children.

Does props change component update?

React components automatically re-render whenever there is a change in their state or props. A simple update of the state, from anywhere in the code, causes all the User Interface (UI) elements to be re-rendered automatically.

Do something when props change React?

To update state when props change in React: Pass the props as dependencies to the useEffect hook. Every time the props change, the logic in useEffect is reran.


2 Answers

AirBnB's Enzyme library provides an elegant solution to this question.

it provides a setProps method, that can be called on either a shallow or jsdom wrapper.

    it("Component should call componentWillReceiveProps on update", () => {         const spy = sinon.spy(Component.prototype, "componentWillReceiveProps");         const wrapper = shallow(<Component {...props} />);          expect(spy.calledOnce).to.equal(false);         wrapper.setProps({ prop: 2 });         expect(spy.calledOnce).to.equal(true);     }); 
like image 162
user1095118 Avatar answered Sep 23 '22 10:09

user1095118


If you re-render the element with different props in the same container node, it will be updated instead of re-mounted. See React.render.

In your case, you should use ReactDOM.render directly instead of TestUtils.renderIntoDocument. The later creates a new container node every time it is called, and thus a new component too.

var node, component; beforeEach(function(){     node = document.createElement('div');     component = ReactDOM.render(<MyComponent value={true} />, node); });  it('should update the state of the component when the value prop is changed', function(){     // `component` will be updated instead of remounted     ReactDOM.render(<MyComponent value={false} />, node);     // Assert that `component` has updated its state in response to a prop change     expect(component.state.value).toBe(false); }); 
like image 31
Alexandre Kirszenberg Avatar answered Sep 22 '22 10:09

Alexandre Kirszenberg