首页 > 解决方案 > Storybook react-native 检查 `CellRenderer` 的渲染方法

问题描述

元素类型无效:应为字符串(用于内置组件)或类/函数(用于复合组件)但得到:未定义。您可能忘记从定义组件的文件中导出组件,或者您可能混淆了默认导入和命名导入。

检查CellRenderer.

错误:元素类型无效:应为字符串(对于内置组件)或类/函数(对于复合组件),但得到:未定义。您可能忘记从定义组件的文件中导出组件,或者您可能混淆了默认导入和命名导入。

检查CellRenderer.

at createFiberFromTypeAndProps (react-dom.development.js:23965)
at createFiberFromElement (react-dom.development.js:23988)
at createChild (react-dom.development.js:13628)
at reconcileChildrenArray (react-dom.development.js:13900)
at reconcileChildFibers (react-dom.development.js:14305)
at reconcileChildren (react-dom.development.js:16762)
at updateHostComponent (react-dom.development.js:17302)
at beginWork (react-dom.development.js:18627)
at HTMLUnknownElement.callCallback (react-dom.development.js:188)
at Object.invokeGuardedCallbackDev (react-dom.development.js:237)

我正在尝试在应该适用于 react-native ios、android 和 web 的组件上使用故事书。

在这种情况下,我们可以在 Storybook 上尝试 web 部件,它似乎可以工作,但问题是当我放一个图标时,它给了我上面列出的问题。

在 obj in date 中按以下方式插入图标:

icon: (item, background) => Icon ({icon: 'user', item, background})

你能帮我个忙吗?

import React from 'react'
import { View } from 'react-native'
import { storiesOf } from '@storybook/react-native'
import { withKnobs, object } from '@storybook/addon-knobs'
import Dashboard from '../Dashboard'

import { FontAwesome } from 'react-native-vector-icons'

const Icon = ({ icon, item, background }) => (
  <FontAwesome
    name={icon}
    size={40}
    color={item.iconColor || (!item.background || !background ? '#3498db' : '#fff')}
    style={item.styleIcon}
  />
)

const data = [
  {
    name: 'Me',
    background: '#3498db',
    icon: (item, background) => Icon({ icon: 'user', item, background }),
    iconColor: '#0d47a1',
    rippleColor: '#000',
  },
  {
    name: 'Family',
    background: '#b71c1c',
    //icon: (item, background) => Icon({ icon: 'gratipay', item, background }),
    styleIcon: { color: '#0d47a1' },
  },
  {
    name: 'Lovely',
    background: '#ffeb3b',
    //icon: (item, background) => Icon({ icon: 'heart', item, background }),
  },
  {
    name: 'Team',
    background: '#4caf50',
    //icon: (item, background) => Icon({ icon: 'users', item, background }),
    styleName: { color: '#0d47a1', fontWeight: 'bold' },
  },
  {
    name: 'Friends',
    nameColor: '#3498db',
    background: '#02cbef',
    //icon: (item, background) => Icon({ icon: 'group', item, background }),
  },
  {
    name: 'Calendars',
    background: '#ff5722',
    //icon: (item, background) => Icon({ icon: 'calendar', item, background }),
  },
]

const card = ({ name }) => console.log('Card: ' + name)

storiesOf('Dashboard', module)
  .addDecorator(withKnobs)
  .add('example', () => (
    <View style={{ alignItems: 'center' }}>
      <Dashboard data={data} background={true} card={card} column={2} rippleColor={'#3498db'} />
    </View>
  ))

仪表板.js

import React, { useState } from 'react'
import { Text, View, StyleSheet, Dimensions, Platform, TouchableNativeFeedback, TouchableOpacity } from 'react-native'
import { FlatGrid } from 'react-native-super-grid'

const { width } = Dimensions.get('window')

const RippleColor = (...args) => (Platform.Version >= 21 ? TouchableNativeFeedback.Ripple(...args) : null)

const Touchable = Platform.OS === 'web' ? TouchableOpacity : TouchableNativeFeedback

function Dashboard({ column = 2, data = [], card = () => {}, background, rippleColor = '#fff', ...props }) {
  const [state, setState] = useState({
    widthDevice: width,
  })
  const { widthDevice } = state

  const onLayout = (e) => {
    const { width: widthDevice } = Dimensions.get('window')
    setState((prev) => ({ ...prev, widthDevice }))
  }
  var dim = widthDevice / column - 20
  return (
    <View onLayout={onLayout} style={{ flex: 1 }}>
      <FlatGrid
        itemDimension={dim}
        data={data}
        style={styles.gridView}
        renderItem={({ item, index }) => (
          <Touchable
            onPress={() => card(item)}
            delayPressIn={0}
            delayPressOut={0}
            useForeground={true}
            background={RippleColor(item.rippleColor || rippleColor)}
          >
            <View
              style={[
                styles.itemContainer,
                {
                  backgroundColor: !item.background || !background ? '#fff' : item.background,
                  height: dim,
                },
              ]}
            >
              {item?.icon && item?.icon(item, background)}
              <Text
                style={[
                  styles.itemName,
                  {
                    color: item.nameColor || (!item.background || !background ? '#000' : '#fff'),
                  },
                  item.styleName,
                ]}
              >
                {item.name || index}
              </Text>
            </View>
          </Touchable>
        )}
        {...props}
      />
    </View>
  )
}

const styles = StyleSheet.create({
  gridView: {
    flex: 1,
  },
  itemContainer: {
    justifyContent: 'center',
    alignItems: 'center',
    borderRadius: 5,
  },
  itemName: {
    fontSize: 16,
    fontWeight: '600',
    paddingTop: 10,
  },
})

export default Dashboard

Webback.config.js

const path = require('path')
const HTMLWebpackPlugin = require('html-webpack-plugin')

const HTMLWebpackPluginConfig = new HTMLWebpackPlugin({
  template: path.resolve(__dirname, './public/index.html'),
  filename: 'index.html',
  inject: 'body',
})

module.exports = {
  entry: path.join(__dirname, 'index.web.js'),
  output: {
    filename: 'bundle.js',
    path: path.join(__dirname, '/build'),
  },
  resolve: {
    alias: {
      'react-native$': 'react-native-web',
      '@storybook/react-native': '@storybook/react',
      'styled-components/native': 'styled-components',
    },
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx|ts|tsx)$/,
        exclude: /node_modules[/\\](?!react-native-vector-icons)/,
        use: {
          loader: 'babel-loader',
          options: {
            // Disable reading babel configuration
            babelrc: false,
            configFile: false,
            presets: [
              '@babel/preset-env',
              '@babel/preset-react',
              '@babel/preset-flow',
              '@babel/preset-typescript',
              {
                plugins: ['@babel/plugin-proposal-class-properties', '@babel/plugin-proposal-object-rest-spread'],
              },
            ],
          },
        },
      },
      {
        test: /\.(js|jsx|ts|tsx)$/,
        exclude: /node_modules[/\\](?!react-native-super-grid)/,
        use: {
          loader: 'babel-loader',
          options: {
            // Disable reading babel configuration
            babelrc: false,
            configFile: false,
            presets: [
              '@babel/preset-env',
              '@babel/preset-react',
              '@babel/preset-flow',
              '@babel/preset-typescript',
              {
                plugins: ['@babel/plugin-proposal-class-properties', '@babel/plugin-proposal-object-rest-spread'],
              },
            ],
          },
        },
      },
      {
        test: /\.(jpg|png|woff|woff2|eot|ttf|svg)$/,
        loader: 'file-loader',
      },
      {
        test: /\.ttf$/,
        loader: 'url-loader', // or directly file-loader
        include: path.resolve(__dirname, 'node_modules/react-native-vector-icons'),
      },
    ],
  },
  plugins: [HTMLWebpackPluginConfig],
  devServer: {
    historyApiFallback: true,
    contentBase: './',
    hot: true,
  },
}

标签: javascriptreactjsreact-nativestorybookreact-native-vector-icons

解决方案


推荐阅读