I have used the below structure to create a react component which is working on the browser after done babel. But the Layout spec is failing in my case since the React is declared in Base component only. Why the inheritance is not working in spec?
Base.js
import React from 'react';
export default class Base extends React.Component {
}
Layout.js
import 'Base' from './Base';
export default class Layout extends Base {
const sample = React.cloneElement(this.props.data, {ref: 't'});
}
Test Case
import Layout from 'component/Layout'
import React from 'react';
describe('Layout', () => {
}
Error message:
ReferenceError: Can't find variable: React
In Layout.js you have the following line
const sample = React.cloneElement(this.props.data, {ref: 't'});
Here you reference React, but Layout.js hasn't got a definition for React, similar to how you don't have access to identifiers in different closures, so it would throw a ReferenceError
If you want to use this reference you need to first teach it to Layout.js by including the import line again
import React from 'react';
If you don't want to have a second import line, you could
Re-export React in Base.js so the one import does both import {foo, bar} from 'baz';
See if you can reference what you want through an identifier you can see, e.g. via Object.getPrototypeOf(Base.prototype).constructor?
As you are creating React as a global in Test Case, the ReferenceError in mocha may be getting thrown too early, moving the import React line above the import Layout line should fix this
Related
I used npm init react-app appname which creates, among other files, App.js. In that file is a function component:
function App() {
return (
<SomeJSX />
);
}
I edited the function component into a class component, like so:
class App extends React.Component{
render() {
return (
<TheSameJSX />
);
}
}
Now, when I run npm start, I get an error:
Failed to compile
src/App.js
Line 4:19: 'React' is not defined no-undef
Search for the keywords to learn more about each error.
I imagine I need to add some setting somewhere that will automatically include React without me needing to explicitly import it at the top of every file. How do I do this? And why does this npm package not do that by default? I know a bit about javascript (and html and css), and have read a bit about React, but I am completely unaware of how npm or webpack works.
Thanks in advance!
EDIT: To clarify, I know how to import stuff with javascript. I can easily add import React from 'react'; to the file and make it work. However, I find it difficult to believe that adding an import statement to every single javascript file is the recommended method, and I don't understand why this example app wouldn't be set up so as to avoid having to do that. Am I mistaken? Do I really need to manually import the same thing over and over again within the same project? Could I set a global variable to React so that I can use it from wherever?
In your default function component you're not extending any classes and just writing a simple function
function App() {
return (
<SomeJSX />
);
}
In class component, you're in fact extending the Class Component by React.Component provided by React default export object and hence you must import it from the package
//only use one of these
import * as React from "react";
import {Component} from "react"; // you can directly extend without writing `React.` with this import
import React from "react"
So your code would be
import React from "react";
class App extends React.Component{
render() {
return (
<TheSameJSX />
);
}
}
Any of the above imports should be fine with a preference to the first and second one.
I've the following import statements using Typescript:
import * as React from 'react';
import { MouseEvent } from 'react'
Typescript complains that I should combine these multiple imports. I've tried the following, but that MouseEvent being imported is different:
import MouseEvent, * as React from 'react'
In this combined import statement, the MouseEvent is different from the one imported through import { MouseEvent } from 'react'.
For some reason, Typescript recognises that the MouseEvent in import { MouseEvent } from 'react'accepts type generics but the MouseEvent in import MouseEvent, * as React from 'react' doesn't.
How can I combine the import statements while still keeping the MouseEvent which has generics?
TypeScript cannot complain about these import statements because they are correct. It is TSLint that can complain about them and cause an error.
There's no way to shorten them to one line. A common way to do this is to use default export that React also provides:
import React, { MouseEvent } from 'react'
A downside is that the package is imported entirely into the bundle and cannot make use of tree shaking.
A safe way to do this is:
import * as React from 'react';
import { MouseEvent } from 'react'
In case this causes TSLint error, respective rule needs to be disabled.
When you’re using import * as React from 'react', you import the whole module into a single variable called React. Therefore, you can access MouseEvent via the React namespace: React.MouseEvent. As you have already imported everything into a single variable, you can’t import something specific in addition.
I was working with some coworkers on a React component, and I had imported React and started to write my class as
import React from 'react'
Class MyComponent extends React.Component
when they suggested I import Component as well, i.e.:
import React, { Component } from 'react'
This is a new pattern to me, and my first reaction was to guess that importing both the namespace and a child module would cause them to be double-imported, as we'd have both a React object and a Component object (which also exists under React).
My second reaction was to think that since objects are passed by reference, both React.Component and Component would reference the same object in memory, so the only real difference is that there'd be an extra (but minimal -- not counting the other modules under React) React object.
However, I'm not sure. Which is correct? Or is neither?
No, the module won't be double-imported. There isn't much difference really between this two ways of importing. The second way makes sense if you have many components in a file, so you can write just extends Component instead of extends React.Component.
In this case,
import React, { Component } from 'react';
is essentially the same as
import React from 'react';
const { Component } = React;
Firstly, I want to say that I am very new to react world. I am using a react component from github in our project. I noticed that the component uses decorators in their code. And, to use that code as it is, I think we have to eject and use babel. But, we don't want to do that, so I plan to remove decorators (multiple) with the native code.
import React from 'react'
import dc from 'dc'
import BaseChart from './base-chart'
import coordinateGridMixin from '../mixins/coordinate-grid-mixin'
import stackMixin from '../mixins/stack-mixin'
import barMixin from '../mixins/bar-mixin'
#barMixin
#stackMixin
#coordinateGridMixin
export default class BarChart extends BaseChart{
static displayName = 'BarChart'
componentDidMount(){
this.chart = dc.barChart(this.chart)
this.configure()
this.chart.render()
}
}
I started this with the following code, with the help of this page.
import React from 'react'
import dc from 'dc'
import BaseChart from './base-chart'
import coordinateGridMixin from '../mixins/coordinate-grid-mixin'
import stackMixin from '../mixins/stack-mixin'
import barMixin from '../mixins/bar-mixin'
import compose from 'recompose'
class BarChart extends BaseChart {
static displayName = 'BarChart'
componentDidMount(){
this.chart = dc.barChart(this.chart)
this.configure()
this.chart.render()
}
}
export default compose(
coordinateGridMixin,
stackMixin,
barMixin
)(BarChart);
Doing this I get an error "export 'default' (imported as 'compose') was not found in 'recompose'
That make me wonder, do I need to use recompose? Or, there is a different and simpler way? Not sure how to replace this piece.
export default ???(
coordinateGridMixin,
stackMixin,
barMixin
)(BarChart);
Any help would be appreciated. I am not sure if I have given enough information to you to help.
Your error is about recompose exporting nothing by default, so your import is incorrect, you should import compose like this :
import { compose } from 'recompose';
You can also chain decorate your component to do it without recompose (not 100% sure about the syntax) :
let decoratedBarChart = coordinateGridMixin(BarChart);
decoratedBarChart = stackMixin(decoratedBarChart);
decoratedBarChart = barMixin(decoratedBarChart);
export default decoratedBarChart;
What is the major benefit of writing
import React, { Component } from 'react';
class Link extends Component {
...
}
instead of
import React from 'react';
class Link extends React.Component {
...
}
when it comes to react 15.4.x??
In my perspective and in my case (correct me if I am wrong) it does not matter at all since:
I am using a webpack2 for making my bundles;
I use code splitting to split my app code from vendor code;
I use webpack.optimize.CommonsChunkPlugin plugin with minChunks: Infinity setting to make sure that all vendor code is included only once.
From understanding how ES6 imports work I understand that by using named import of {Component} I state that I want to use only Component component in my code, which looks.. cleaner.
But since whole React package is still used in the app, I can create my classes with extension from React.Component instead of just Component and in result webpack will still produce the same amount of code and my bundle size will be the same in both cases.
Am I correct?
There is no difference, React.Component is the same object as Component, the second way is more eloquent in my opinion, because it really explains that you are using the Component object from the React library.
The first one seems to refer a member,
but, it comes from the pre modules era of javascript, where everything had to be attached to the exported global namespace (just to avoid global namespace pollution).
something that could be under the hood:
// this should be assumed as an example only.
class React { ... }
class Component { ... }
React.Component = Component;
// ES6
export {Component}
export default React;
// ES5
window.React = React;
Note: as someone said, you also need to import React because JSX needs to have it on scope, but, if you want to avoid it, you can expose React globally (window.React = React)
This import statement:
import React, { Component } from 'react';
is really doing two things. It imports the default export, under the name React (which is just a convention, you could call it what you want). It also imports a named export, Component.
The reason that the default React is imported is actually to make JSX work. When your JSX code is transpiled, then it substitutes <div> for React.DOM.div(), so React must exist otherwise things break!
Importing both things separately means that your JSX works but you get to write Component instead of React.Component in your code.
When you do import anything from "react", then the whole file is going to get included either way - any attempt to reduce the bundle size (e.g. Dead Code Elimination, Tree Shaking) is an additional, separate step, which doesn't depend on your import statements but the parts of the code that you use.
In the case of this library, the sane thing happens: the child Component of the default export refers to the same thing as the named export Component.
However, bear in mind that this isn't guaranteed to be the case! If the React library code contained the following:
export default {
Component: "foo"
};
export const Component = "bar";
Then React.Component === "foo" and Component === "bar".