api返回结果以及改状态这些逻辑可以放在storybook里吗?还是需要mock?

ywang04
  • 4
新手上路,请多包涵
export const AsyncSearch = (args) => {
  const SEARCH_URI = 'https://api.github.com/search/users';
  const [isLoading, setIsLoading] = useState(false);
  const [options, setOptions] = useState([]);
  const handleSearch = (query) => {
    setIsLoading(true);
    fetch(`${SEARCH_URI}?q=${query}+in:login&page=1&per_page=10`)
      .then((resp) => resp.json())
      .then(({ items }) => {
        const options = items.map((i) => ({
          avatar_url: i.avatar_url,
          id: i.id,
          login: i.login,
        }));

        setOptions(options);
        setIsLoading(false);
      });
  };
  return (
    <TypeaheadAdvancedSearch
      options={options}
      handleSearch={handleSearch}
      isLoading={isLoading}
      {...args}
    />
  );
};
AsyncSearch.args = {
  id: 'async-advance-search',
  isAsync: true,
  labelKey: 'login',
  searchText: 'Searching...',
  filterBy: () => true,
};

我在为TypeaheadAdvancedSearch 这个component写一个story叫做AsyncSearch(如上图所示)。 因为需要发api request在后端做search 然后搜索到的数据options和isLoading作为props 传给这个component. 目前后端api还没有完成 所以我用了一个public api https://api.github.com/search/users 作为demo。请问下面这段逻辑是否可以放在storybook里 还是我需要做mock?我的理解是storybook里的component都是隔离的 需要通过传递不同的props显示不同的样子,但是API获取数据这种业务逻辑是否应该放在里面? 如果不放在里面 我又不知道如何mock api 并且返回的mock数据和修改isLoading的状态

const SEARCH_URI = 'https://api.github.com/search/users';
  const [isLoading, setIsLoading] = useState(false);
  const [options, setOptions] = useState([]);
  const handleSearch = (query) => {
    setIsLoading(true);
    fetch(`${SEARCH_URI}?q=${query}+in:login&page=1&per_page=10`)
      .then((resp) => resp.json())
      .then(({ items }) => {
        const options = items.map((i) => ({
          avatar_url: i.avatar_url,
          id: i.id,
          login: i.login,
        }));

        setOptions(options);
        setIsLoading(false);
      });
  };
回复
阅读 573
1 个回答

我平常用 Storybook 主要是用来做展示组件,以及测试用,在这两种场景中,都没有必要去引用外部的数据,更合适的是根据需要去构造数据,提供给组件,从而让组件展示特定的状态.
如果你也是在以上类似场景中使用的话,也应该根据需要(为了展示组件,为了测试某些边界条件之类的)去构造指定的数据,从外部引入数据会额外增加复杂性,并且会使展示或者测试的结果变的更脆弱.

const Template = (args) => <TypeaheadAdvancedSearch {...args} />

const options = [
  {
    avatar_url: 'https://avatar/a.png',
    id: 1,
    login: 'a',
  },
  {
    avatar_url: 'https://avatar/b.png',
    id: 2,
    login: 'b',
  },
]

// 展示组件正常渲染状态
export const Default = Template.bind({})
Default.args = {
  options,
}

// 展示加载状态
export const Loading = Template.bind({})
Loading.args = {
  options: {},
  isLoading: true,
}

// 当出现数据错误时,组件的状态
export const Error = Template.bind({})
Error.args = {
  options: null,
}

另外你这个获取数据的逻辑本来就不再这个组件里,就更没必要放进来了.
如果说有个组件,组件的内部带有获取外部数据的逻辑,而你又想在 Storybook 里面展示的话,那就要看你想要用来做什么了,如果是用来做测试的,那肯定是要 mock 的,如果只是展示的话,其实也直接渲染出来也可以.
但更推荐的做法是,把获取数据的逻辑和组件分开来,分成基础的展示组件和包含获取数据逻辑的容器组件,然后单独将展示组件导入到 story 里面来操作就方便很多.
另外一种做法是使用 Apollo 或者 Redux 之类的数据管理库,直接用社区现成的工具来模拟数据,会方便很多.
你可以看看 Stroybook 的教程,里面都有更详细的介绍 Intro to Storybook

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏