Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set initial state for useState Hook in jest and enzyme?

Currently Im using functional component with react hooks. But I'm unable to test the useState hook completely. Consider a scenario like, in useEffect hook I'm doing an API call and setting value in the useState. For jest/enzyme I have mocked data to test but I'm unable to set initial state value for useState in jest.

const [state, setState] = useState([]);

I want to set initial state as array of object in jest. I could not find any setState function as similar like class component.

like image 348
Srigar Avatar asked Jul 14 '19 08:07

Srigar


People also ask

How do I change my initial state of useState?

To set a conditional initial value for useState in React:Pass a function to the useState hook. Use a condition to determine the correct initial value for the state variable. The function will only be invoked on the initial render.

How do I change state with useState hook?

To update the state, call the state updater function with the new state setState(newState) . Alternatively, if you need to update the state based on the previous state, supply a callback function setState(prevState => newState) .

How do you initialize a state in React hooks?

If you want to set initial state after loading data (fetch data from api) you can use "useEffect" in React hooks. it is equal to "componentWillReceiveProps" in class component. so when you set state value in useEffect make sure avoid infinity loop eg ..


2 Answers

You can mock React.useState to return a different initial state in your tests:

// Cache original functionality const realUseState = React.useState  // Stub the initial state const stubInitialState = ['stub data']  // Mock useState before rendering your component jest   .spyOn(React, 'useState')   .mockImplementationOnce(() => realUseState(stubInitialState)) 

Reference: https://dev.to/theactualgivens/testing-react-hook-state-changes-2oga

like image 73
Jimmy Avatar answered Sep 25 '22 09:09

Jimmy


First, you cannot use destructuring in your component. For example, you cannot use:

import React, { useState } from 'react'; const [myState, setMyState] = useState(); 

Instead, you have to use:

import React from 'react' const [myState, setMyState] = React.useState(); 

Then in your test.js file:

test('useState mock', () => {    const myInitialState = 'My Initial State'     React.useState = jest.fn().mockReturnValue([myInitialState, {}])        const wrapper = shallow(<MyComponent />)     // initial state is set and you can now test your component  } 

If you use useState hook multiple times in your component:

// in MyComponent.js  import React from 'react'  const [myFirstState, setMyFirstState] = React.useState(); const [mySecondState, setMySecondState] = React.useState();  // in MyComponent.test.js  test('useState mock', () => {    const initialStateForFirstUseStateCall = 'My First Initial State'    const initialStateForSecondUseStateCall = 'My Second Initial State'     React.useState = jest.fn()      .mockReturnValueOnce([initialStateForFirstUseStateCall, {}])      .mockReturnValueOnce([initialStateForSecondUseStateCall, {}])        const wrapper = shallow(<MyComponent />)     // initial states are set and you can now test your component  } // actually testing of many `useEffect` calls sequentially as shown // above makes your test fragile. I would recommend to use  // `useReducer` instead. 
like image 38
Si Thu Avatar answered Sep 23 '22 09:09

Si Thu