admin管理员组

文章数量:1323173

Newbie here, so apologies in advance if I am overlooking something obvious or missed a duplicate posting (and also for not posting directly on styled-ponents, apparently I need a rep for that...) .

The closest I found to my problem was in this resolved issue, at the bottom of the thread:

The guy had a very similar problem, but the solution was brief and Typescript specific.

BACKGROUND: I have an index file that imports my ponents from all over, and exports them under a webpack alias. Whenever I need to import elsewhere I just declare:

import { MyComponentA, MyComponentB, MyComponentC } from 'ponents';

I recently started incorporating styled-ponents into my project and have been getting an error like the following when I try to style ponents imported in this way:

Error: Cannot create styled-ponent for ponent: undefined._____________styled-ponents.browser.esm.js:233
   at new StyledComponentsError (/home/jhillert/Dropbox/Projects/TimeLockr/node_modules/styled-ponents/dist/styled-ponents.browser.esm.js:233:59)
   at constructWithOptions (/home/jhillert/Dropbox/Projects/TimeLockr/node_modules/styled-ponents/dist/styled-ponents.browser.esm.js:1355:12)
   at styled (/home/jhillert/Dropbox/Projects/TimeLockr/node_modules/styled-ponents/dist/styled-ponents.browser.esm.js:2293:11)
   at Module.eval (/home/jhillert/Dropbox/Projects/TimeLockr/src/ponents/card-area/CardArea.jsx:111:91)
   at eval (/home/jhillert/Dropbox/Projects/TimeLockr/src/ponents/card-area/CardArea.jsx:133:31)
   at Module../src/ponents/card-area/CardArea.jsx (http://localhost:8080/bundle.js:9343:1)
   at __webpack_require__ (http://localhost:8080/bundle.js:724:30)
   at fn (http://localhost:8080/bundle.js:101:20)
   at eval (/home/jhillert/Dropbox/Projects/TimeLockr/src/indexes/ponents.jsx:17:89)
   at Module../src/indexes/ponents.jsx (http://localhost:8080/bundle.js:9619:1)

If I import the ponent directly from the source file I do not get the error. It only happens when I try to pass ponents imported from the index file into the styled() method, and also when I try to use the CSS prop to add inline styling.

For some reason the error does not occur with all ponents imported in this way, and also I have made changes to my code that suddenly cause the index import to trigger the error. I really like having a central index file, so a fix would be greatly appreciated.

Example where css prop causes error:

*Project config below. Index File looks like this (ponents.jsx):

export { default as ActionBar } from '../ponents/action-bar/ActionBar';
export { default as AuthForm } from '../ponents/auth/AuthForm';
export { default as AuthModal } from '../ponents/auth/AuthModal';
export { default as AuthTabs } from '../ponents/auth/AuthTabs';
export { default as Box } from '../ponents/box/Box';

/*==============================================================*/

//CardArea.js
import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-ponents';
import {
  CardColumn  ◀◀◀—————————————— DOES PRODUCE ERROR
  LockedEntryCard,
  ReleasedEntryCard,
} from 'ponents';

import CardColumn from '../card-column/CardColumn' ◀◀◀——————— DOES NOT

const S = {};

S.CardArea = styled.div`  ◀◀◀————— NOT IMPORTED, NOT A PROBLEM
     /* ommitted */                BUT WOULD CAUSE SAME ERROR 
`;                                 IF IMPORTED.

const CardArea = ({ entries, refresh }) => {
  const { locked, released } = entries;
  const hasLockedChildren = !!(locked.length);
  const hasReleasedChildren = !!(released.length);

  const [showLocked, updateShowLocked] = useState(false);
  const [showReleased, updateShowReleased] = useState(false);

  useEffect(() => {
      updateShowLocked(true);
      updateShowReleased(true);
    },
    []);

  return (
    <S.CardArea>
      {(hasReleasedChildren && showReleased)
        && (
          <CardColumn
            id='card-column-released-entries'
            css='                   ◀◀◀ TRIGGERS THE ERROR
              margin-left = 2rem;   ◀◀◀ TRIGGERS THE ERROR
              margin-right = 1rem;  ◀◀◀ TRIGGERS THE ERROR
            '                       ◀◀◀ TRIGGERS THE ERROR
            heading='Unlocked'
            Card={ReleasedEntryCard}

      /* ommitted */

CardArea.propTypes = {
    /* ommitted */
};

export default CardArea;

=================================================================

Webpack configuration (webpack.config.js):

Aliases are towards the bottom.

const webpack = require('webpack');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const Dotenv = require('dotenv-webpack');
const path = require('path');

const config = {
  entry: './src/index.jsx',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js',
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        use: 'babel-loader',
        exclude: /node_modules/,
      },
      {
        test: /\.jsx?$/,
        include: /node_modules/,
        use: ['react-hot-loader/webpack'],
      },
      {
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader/locals',
        ],
      },
      {
        test: /\.less$/,
        use: [
          'style-loader',
          'css-loader',
          'less-loader',
        ],
      },
      {
        test: /\.png$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              mimetype: 'image/png',
            },
          },
        ],
      },
    ],
  },
  node: {
    console: true,
    fs: 'empty',
    net: 'empty',
    tls: 'empty',
  },
  plugins: [
    new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /en/),
  ],
  plugins: [
    new CopyWebpackPlugin([
      // relative path is from src
      { from: './static/favicon.ico' }, // <- your path to favicon
    ]),
    new Dotenv({
      systemvars: true,
    }),
  ],
  devServer: {
    contentBase: './dist',
  },
  resolve: {
    extensions: ['.js', '.jsx', '.css'],
    alias: {
      ponents: path.resolve(__dirname, 'src/indexes/ponents.jsx'),
      contexts: path.resolve(__dirname, 'src/indexes/contexts.jsx'),
      theme: path.resolve(__dirname, 'src/indexes/theme.jsx'),
      utilities: path.resolve(__dirname, 'src/indexes/utilities.jsx'),
    },
  },
};

module.exports = config;

Babel Config (.bablerc):

{
  presets: [
    [
      '@babel/preset-env',
      {
        modules: false
      }
    ],
    '@babel/preset-react'
  ],
  plugins: [
    'react-hot-loader/babel',
    '@babel/plugin-proposal-class-properties',
    '@babel/plugin-transform-react-jsx-source',
    [
      'babel-plugin-styled-ponents',
      {
        "ssr": false
      }
    ],
  ]
}

Dependencies (Package.json)

{
  "name": "timelockr",
  "version": "1.0.0",
  "description": "Making information inaccessible.",
  "main": "index.js",
  "keywords": [],
  "author": "",
  "license": "ISC",
  "repository": {
    "type": "git",
    "url": ""
  },
  "scripts": {
    "clean": "rm dist/bundle.js",
    "build-dev": "webpack -d --mode development",
    "build-prod": "webpack -p --mode production",
    "dev-server": "nodemon --ignore node_modules --inspect server",
    "start": "webpack-dev-server --host 0.0.0.0 --hot --mode development",
    "start:dev": "nodenv -f .",
    "lint:css": "stylelint './src/**/*.js'"
  },
  "dependencies": {
    "@date-io/date-fns": "^1.1.0",
    "@date-io/moment": "^1.1.0",
    "@material-ui/core": "^3.9.3",
    "@material-ui/icons": "^3.0.2",
    "@material-ui/styles": "^4.0.0-alpha.4",
    "@material-ui/system": "^3.0.0-alpha.2",
    "ajv": "^6.10.0",
    "axios": "^0.18.0",
    "bluebird": "^3.5.3",
    "body-parser": "^1.18.3",
    "bootstrap": "^4.3.1",
    "classnames": "^2.2.6",
    "cors": "^2.8.5",
    "date-fns": "^2.0.0-alpha.27",
    "debug": "^4.1.1",
    "dotenv-webpack": "^1.7.0",
    "express": "^4.16.4",
    "express-mysql-session": "^2.1.0",
    "express-session": "^1.15.6",
    "jquery": "^3.3.1",
    "less": "^3.9.0",
    "material-ui-pickers": "^2.2.4",
    "moment": "^2.24.0",
    "mysql": "^2.16.0",
    "notistack": "^0.6.1",
    "pbkdf2-password": "^1.2.1",
    "prop-types": "^15.7.2",
    "react": "^16.8.6",
    "react-bootstrap": "^1.0.0-beta.6",
    "react-copy-to-clipboard": "^5.0.1",
    "react-dom": "^16.8.6",
    "react-hot-loader": "^4.8.2",
    "react-router-dom": "^5.0.0",
    "react-transition-group": "^2.7.1",
    "styled-ponents": "^4.2.0",
    "typeface-roboto": "0.0.54"
  },
  "devDependencies": {
    "@babel/core": "^7.4.0",
    "@babel/plugin-proposal-class-properties": "^7.4.0",
    "@babel/preset-env": "^7.4.2",
    "@babel/preset-react": "^7.0.0",
    "async": "^2.6.2",
    "babel-eslint": "^10.0.1",
    "babel-loader": "^8.0.5",
    "babel-plugin-styled-ponents": "^1.10.0",
    "babel-plugin-transform-react-jsx-source": "^6.22.0",
    "copy-webpack-plugin": "^5.0.2",
    "css-loader": "^1.0.0",
    "eslint": "^5.16.0",
    "eslint-config-airbnb": "^17.1.0",
    "eslint-import-resolver-webpack": "^0.11.0",
    "eslint-plugin-import": "^2.16.0",
    "eslint-plugin-jsx-a11y": "^6.2.1",
    "eslint-plugin-react": "^7.12.4",
    "eslint-plugin-react-hooks": "^1.6.0",
    "eslint_d": "^7.3.0",
    "faker": "^4.1.0",
    "less-loader": "^4.1.0",
    "node-cmd": "^3.0.0",
    "nodemon": "^1.18.10",
    "style-loader": "^0.23.1",
    "stylelint": "^9.10.1",
    "stylelint-config-remended": "^2.1.0",
    "stylelint-config-styled-ponents": "^0.1.1",
    "stylelint-processor-styled-ponents": "^1.6.0",
    "url-loader": "^1.1.2",
    "webpack": "^4.29.6",
    "webpack-cli": "^3.3.0",
    "webpack-dev-server": "^3.2.1"
  }
}

Newbie here, so apologies in advance if I am overlooking something obvious or missed a duplicate posting (and also for not posting directly on styled-ponents, apparently I need a rep for that...) .

The closest I found to my problem was in this resolved issue, at the bottom of the thread: https://github./styled-ponents/styled-ponents/issues/213

The guy had a very similar problem, but the solution was brief and Typescript specific.

BACKGROUND: I have an index file that imports my ponents from all over, and exports them under a webpack alias. Whenever I need to import elsewhere I just declare:

import { MyComponentA, MyComponentB, MyComponentC } from 'ponents';

I recently started incorporating styled-ponents into my project and have been getting an error like the following when I try to style ponents imported in this way:

Error: Cannot create styled-ponent for ponent: undefined._____________styled-ponents.browser.esm.js:233
   at new StyledComponentsError (/home/jhillert/Dropbox/Projects/TimeLockr/node_modules/styled-ponents/dist/styled-ponents.browser.esm.js:233:59)
   at constructWithOptions (/home/jhillert/Dropbox/Projects/TimeLockr/node_modules/styled-ponents/dist/styled-ponents.browser.esm.js:1355:12)
   at styled (/home/jhillert/Dropbox/Projects/TimeLockr/node_modules/styled-ponents/dist/styled-ponents.browser.esm.js:2293:11)
   at Module.eval (/home/jhillert/Dropbox/Projects/TimeLockr/src/ponents/card-area/CardArea.jsx:111:91)
   at eval (/home/jhillert/Dropbox/Projects/TimeLockr/src/ponents/card-area/CardArea.jsx:133:31)
   at Module../src/ponents/card-area/CardArea.jsx (http://localhost:8080/bundle.js:9343:1)
   at __webpack_require__ (http://localhost:8080/bundle.js:724:30)
   at fn (http://localhost:8080/bundle.js:101:20)
   at eval (/home/jhillert/Dropbox/Projects/TimeLockr/src/indexes/ponents.jsx:17:89)
   at Module../src/indexes/ponents.jsx (http://localhost:8080/bundle.js:9619:1)

If I import the ponent directly from the source file I do not get the error. It only happens when I try to pass ponents imported from the index file into the styled() method, and also when I try to use the CSS prop to add inline styling.

For some reason the error does not occur with all ponents imported in this way, and also I have made changes to my code that suddenly cause the index import to trigger the error. I really like having a central index file, so a fix would be greatly appreciated.

Example where css prop causes error:

*Project config below. Index File looks like this (ponents.jsx):

export { default as ActionBar } from '../ponents/action-bar/ActionBar';
export { default as AuthForm } from '../ponents/auth/AuthForm';
export { default as AuthModal } from '../ponents/auth/AuthModal';
export { default as AuthTabs } from '../ponents/auth/AuthTabs';
export { default as Box } from '../ponents/box/Box';

/*==============================================================*/

//CardArea.js
import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-ponents';
import {
  CardColumn  ◀◀◀—————————————— DOES PRODUCE ERROR
  LockedEntryCard,
  ReleasedEntryCard,
} from 'ponents';

import CardColumn from '../card-column/CardColumn' ◀◀◀——————— DOES NOT

const S = {};

S.CardArea = styled.div`  ◀◀◀————— NOT IMPORTED, NOT A PROBLEM
     /* ommitted */                BUT WOULD CAUSE SAME ERROR 
`;                                 IF IMPORTED.

const CardArea = ({ entries, refresh }) => {
  const { locked, released } = entries;
  const hasLockedChildren = !!(locked.length);
  const hasReleasedChildren = !!(released.length);

  const [showLocked, updateShowLocked] = useState(false);
  const [showReleased, updateShowReleased] = useState(false);

  useEffect(() => {
      updateShowLocked(true);
      updateShowReleased(true);
    },
    []);

  return (
    <S.CardArea>
      {(hasReleasedChildren && showReleased)
        && (
          <CardColumn
            id='card-column-released-entries'
            css='                   ◀◀◀ TRIGGERS THE ERROR
              margin-left = 2rem;   ◀◀◀ TRIGGERS THE ERROR
              margin-right = 1rem;  ◀◀◀ TRIGGERS THE ERROR
            '                       ◀◀◀ TRIGGERS THE ERROR
            heading='Unlocked'
            Card={ReleasedEntryCard}

      /* ommitted */

CardArea.propTypes = {
    /* ommitted */
};

export default CardArea;

=================================================================

Webpack configuration (webpack.config.js):

Aliases are towards the bottom.

const webpack = require('webpack');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const Dotenv = require('dotenv-webpack');
const path = require('path');

const config = {
  entry: './src/index.jsx',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js',
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        use: 'babel-loader',
        exclude: /node_modules/,
      },
      {
        test: /\.jsx?$/,
        include: /node_modules/,
        use: ['react-hot-loader/webpack'],
      },
      {
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader/locals',
        ],
      },
      {
        test: /\.less$/,
        use: [
          'style-loader',
          'css-loader',
          'less-loader',
        ],
      },
      {
        test: /\.png$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              mimetype: 'image/png',
            },
          },
        ],
      },
    ],
  },
  node: {
    console: true,
    fs: 'empty',
    net: 'empty',
    tls: 'empty',
  },
  plugins: [
    new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /en/),
  ],
  plugins: [
    new CopyWebpackPlugin([
      // relative path is from src
      { from: './static/favicon.ico' }, // <- your path to favicon
    ]),
    new Dotenv({
      systemvars: true,
    }),
  ],
  devServer: {
    contentBase: './dist',
  },
  resolve: {
    extensions: ['.js', '.jsx', '.css'],
    alias: {
      ponents: path.resolve(__dirname, 'src/indexes/ponents.jsx'),
      contexts: path.resolve(__dirname, 'src/indexes/contexts.jsx'),
      theme: path.resolve(__dirname, 'src/indexes/theme.jsx'),
      utilities: path.resolve(__dirname, 'src/indexes/utilities.jsx'),
    },
  },
};

module.exports = config;

Babel Config (.bablerc):

{
  presets: [
    [
      '@babel/preset-env',
      {
        modules: false
      }
    ],
    '@babel/preset-react'
  ],
  plugins: [
    'react-hot-loader/babel',
    '@babel/plugin-proposal-class-properties',
    '@babel/plugin-transform-react-jsx-source',
    [
      'babel-plugin-styled-ponents',
      {
        "ssr": false
      }
    ],
  ]
}

Dependencies (Package.json)

{
  "name": "timelockr",
  "version": "1.0.0",
  "description": "Making information inaccessible.",
  "main": "index.js",
  "keywords": [],
  "author": "",
  "license": "ISC",
  "repository": {
    "type": "git",
    "url": "https://github./jehillert/Keep-Away"
  },
  "scripts": {
    "clean": "rm dist/bundle.js",
    "build-dev": "webpack -d --mode development",
    "build-prod": "webpack -p --mode production",
    "dev-server": "nodemon --ignore node_modules --inspect server",
    "start": "webpack-dev-server --host 0.0.0.0 --hot --mode development",
    "start:dev": "nodenv -f .",
    "lint:css": "stylelint './src/**/*.js'"
  },
  "dependencies": {
    "@date-io/date-fns": "^1.1.0",
    "@date-io/moment": "^1.1.0",
    "@material-ui/core": "^3.9.3",
    "@material-ui/icons": "^3.0.2",
    "@material-ui/styles": "^4.0.0-alpha.4",
    "@material-ui/system": "^3.0.0-alpha.2",
    "ajv": "^6.10.0",
    "axios": "^0.18.0",
    "bluebird": "^3.5.3",
    "body-parser": "^1.18.3",
    "bootstrap": "^4.3.1",
    "classnames": "^2.2.6",
    "cors": "^2.8.5",
    "date-fns": "^2.0.0-alpha.27",
    "debug": "^4.1.1",
    "dotenv-webpack": "^1.7.0",
    "express": "^4.16.4",
    "express-mysql-session": "^2.1.0",
    "express-session": "^1.15.6",
    "jquery": "^3.3.1",
    "less": "^3.9.0",
    "material-ui-pickers": "^2.2.4",
    "moment": "^2.24.0",
    "mysql": "^2.16.0",
    "notistack": "^0.6.1",
    "pbkdf2-password": "^1.2.1",
    "prop-types": "^15.7.2",
    "react": "^16.8.6",
    "react-bootstrap": "^1.0.0-beta.6",
    "react-copy-to-clipboard": "^5.0.1",
    "react-dom": "^16.8.6",
    "react-hot-loader": "^4.8.2",
    "react-router-dom": "^5.0.0",
    "react-transition-group": "^2.7.1",
    "styled-ponents": "^4.2.0",
    "typeface-roboto": "0.0.54"
  },
  "devDependencies": {
    "@babel/core": "^7.4.0",
    "@babel/plugin-proposal-class-properties": "^7.4.0",
    "@babel/preset-env": "^7.4.2",
    "@babel/preset-react": "^7.0.0",
    "async": "^2.6.2",
    "babel-eslint": "^10.0.1",
    "babel-loader": "^8.0.5",
    "babel-plugin-styled-ponents": "^1.10.0",
    "babel-plugin-transform-react-jsx-source": "^6.22.0",
    "copy-webpack-plugin": "^5.0.2",
    "css-loader": "^1.0.0",
    "eslint": "^5.16.0",
    "eslint-config-airbnb": "^17.1.0",
    "eslint-import-resolver-webpack": "^0.11.0",
    "eslint-plugin-import": "^2.16.0",
    "eslint-plugin-jsx-a11y": "^6.2.1",
    "eslint-plugin-react": "^7.12.4",
    "eslint-plugin-react-hooks": "^1.6.0",
    "eslint_d": "^7.3.0",
    "faker": "^4.1.0",
    "less-loader": "^4.1.0",
    "node-cmd": "^3.0.0",
    "nodemon": "^1.18.10",
    "style-loader": "^0.23.1",
    "stylelint": "^9.10.1",
    "stylelint-config-remended": "^2.1.0",
    "stylelint-config-styled-ponents": "^0.1.1",
    "stylelint-processor-styled-ponents": "^1.6.0",
    "url-loader": "^1.1.2",
    "webpack": "^4.29.6",
    "webpack-cli": "^3.3.0",
    "webpack-dev-server": "^3.2.1"
  }
}

Share Improve this question edited Apr 7, 2019 at 1:55 etarhan 4,1762 gold badges17 silver badges29 bronze badges asked Apr 6, 2019 at 18:41 jehillertjehillert 4521 gold badge6 silver badges16 bronze badges 7
  • import foo from 'bar' imports default export while import {foo} from 'bar' imports variable foo from file bar. – Zydnar Commented Apr 6, 2019 at 18:55
  • In the individual ponent files, there is only default export. So I have been leaving the braces off when directly importing without issue. But the index file exports multiple ponents under one name. Aren’t the braces required? Or can I structure the index file in a different that would circumvent the error and still let me use aliases? – jehillert Commented Apr 6, 2019 at 19:38
  • You can use both - it depends how the imported source is created - braces have the same function as destructiong assigment const {a, b, c} = objWithABCProps If impoted file have eg. only default export and it's object - using braces import will destruct public props. – Zydnar Commented Apr 6, 2019 at 20:07
  • Propably most confusing thing about default export - name in default export doesn't matter - if you default export const foo, you can import bar and it's foo no matter the name, but braces exports are named exports. – Zydnar Commented Apr 6, 2019 at 20:11
  • @John so the error only throws when you try to do styled(ImportedComponent) and when u try to call css on a imported ponent through the index file? In other words just using <ImportedComponent /> gives no issues even when imported through the index file, as long as you don't try to add styles to it? – etarhan Commented Apr 6, 2019 at 23:52
 |  Show 2 more ments

1 Answer 1

Reset to default 6

The following github issues from the arc repo seem to describe problems similar to the one you are having here: #339, #130. The last issue specifically has this ment which suggests a potential solution. By styling in the following manner in most cases the problem is said to be resolved:

const StyledCComponent = styled(props => <CComponent {...props} />)``

The root underlying cause seem to be a circular dependency issue. By wrapping the ponent in a function the dependency is evaluated at runtime.

本文标签: