Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React hooks can't work inside storybook for react native

Technologies

  • React(17.0.2)
  • React Native(0.66.4)
  • TypeScript(4.4.4)
  • Storybook
    • @storybook/react-native(5.3.25)
    • @storybook/react-native-server(5.3.23)

What I'm facing

I'm facing the following react hook error in my Storybook.

Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.

Source code that I'm facing the error

import React, { useState } from "react";
import { Button, Text, View } from "react-native";
import { storiesOf } from "@storybook/react-native";
import CenterView from "../../../storybook/stories/CenterView";
import Modal from "react-native-modal";

storiesOf("components/modal", module)
  .addDecorator(getStory => <CenterView>{getStory()}</CenterView>)
  .add("Modal", () => {
    const [isVisible, setIsVisible] = useState<boolean>(false); // This line doesn't work
    return (
      <View>
        <Button title={"Open Modal"} onPress={() => setIsVisible(true)} />
        <Modal
          isVisible
        >
          <Text>This is modal</Text>
        </Modal>
      </View>
    );
  });

I know this line is the cause of error, but I'm not sure how to fix this.

:

const [isVisible, setIsVisible] = useState<boolean>(false); // This line doesn't work

:
like image 925
Satoru Kikuchi Avatar asked Jun 23 '26 04:06

Satoru Kikuchi


1 Answers

The error is happening, because hooks cannot be called outside of a React component. I would recommend using controls to open the Modal instead, and let Storybook handle the state.

To get this working as-is, you should be able to implement a wrapper component and use that as the second argument to the story:

storiesOf("components/modal", module)
  .addDecorator(getStory => <CenterView>{getStory()}</CenterView>)
  .add("Modal", () => <StoryWrapper />);

function StoryWrapper() {
  const [isVisible, setIsVisible] = useState<boolean>(false);

  return (
    <View>
      <Button title={"Open Modal"} onPress={() => setIsVisible(true)} />
      <Modal isVisible={isVisible}>
        <Text>This is modal</Text>
      </Modal>
    </View>
  );
}
like image 140
Ezra Avatar answered Jun 24 '26 18:06

Ezra



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!