Export default class and function from a React class - javascript

Ho can I export both a class and a function from a react class.
Below is my class and I'm trying to export the onKeyHandler to unit test it. I tried just adding export before the onKeyHandler but my linter didn't like that. How would I go about exporting both one as a default and the other as a function to test.
import React, { Component } from 'react';
class MyComponent extends Component {
onKeyHandler = ({ target, keyCode }) => {
};
render() {
return (
<div>
sdfsdfds
</div>
);
}
}
export default MyComponent;

To export a function, it has to be outside the class. But you can test it without exporting.
Try this with sinon
// import
import 'sinon' from sinon.
// in your test case
let onKeySpy = sinon.spy(MyComponent, "onKeyHandler");
// logic goes here
expect(onKeySpy.called).toBeTrue();
I haven't tried this but this should work. You can spy in a similar way with jest.spyOn() as well.
If you need to stub the method, you can use prototype
let onKeyStub = sinon.stub(MyComponent.prototype, "onKeyHandler");

Related

React JS: How can I export different components based on environment variable?

React JS code:
I want the src/app.jsx to do export default App when the REACT_APP_AUTH_SERVER variable in .env does not exist or have other value, and do export default withAuthenticator(App) when the REACT_APP_AUTH_SERVER variable in .env does exist, and has value aws-cognito:
src/app.jsx:
import React, { Component } from 'react';
import SecuredGate from './SecuredGate/SecuredGate';
import { withAuthenticator } from '#aws-amplify/ui-react'
import './App.css';
import '../fontStyles.css';
class App extends Component {
render() {
return (
<div>
<SecuredGate />
</div>
);
}
}
const Result = () => {
if (process.env.REACT_APP_AUTH_SERVER && process.env.REACT_APP_AUTH_SERVER === "aws-cognito"){
return withAuthenticator(App);
}
return App;
}
// export default App;
// export default withAuthenticator(App)
export default Result;
However, this is not working.
If I do:
export default App;
// export default withAuthenticator(App)
, it works, and if I do:
// export default App;
export default withAuthenticator(App)
it works as well.
So what am I missing?
I think the problem is that the Result component returns a component instead of an element. To understand this better look at what App component does when called with <App />. It runs the code in its body and returns some markup. But what happens if you call <Result />. It will run the code in its block and return another component (a function). So to solve this you can try:
const Result = (process.env.REACT_APP_AUTH_SERVER && process.env.REACT_APP_AUTH_SERVER === "aws-cognito")
? withAuthenticator(App)
: App;
}
export default Result;

Export pure functional component without decorators

I'm trying to export a component without the decorators (connect() in this case)
for unit testing with jest.
So, how could I do this:
import React, { Component } from 'react';
import { connect } from 'react-redux';
export class Header extends Component {
render(){
return <pre>Header</pre>
}
}
export default connect()(Header);
With this component (the export at the beginning doesn't work, it stills exports the connected component)
export let Header = props => {
render(){
return <pre>Header</pre>
}
}
Header = connect()(Header);
export default Header;
Use different variable for your connected component as the following code:
export let Header = props => {
render(){
return <pre>Header</pre>
}
}
let HeaderConnected = connect()(Header);
export default HeaderConnected;
Now you can import your Header freely without using connect()
This can be done without even changing default export:
export let Header = props => {
render(){
return <pre>Header</pre>
}
}
export default connect()(Header);
There may be no need to export original component for connect alone because most well-designed HOCs expose original component:
import Header from '...';
const OriginalHeader = Header.WrappedComponent;

export default something() meaning

I was going through React Navigation docs and I encountered something like this over there:
import Ionicons from 'react-native-vector-icons/Ionicons';
import { createBottomTabNavigator } from 'react-navigation';
export default createBottomTabNavigator(
{
Now, I am unable to comprehend what this line does:
export default createBottomTabNavigator(
I mean it definitely exports something but is it a function?
If yes, then shouldn't it be like:
export default function createBottomTabNavigator(
or According to ES6 something like this:
export default function createBottomTabNavigator = () =>{
The code is equivalent to
const MyBottomTabNavigator = createBottomTabNavigator( { /* ... */ });
export default MyBottomTabNavigator;
The function is called, an Object is returned. The Object is exported and used elsewhere.
Edit:
More example code in the same vein:
const rootOf2 = Math.sqrt(2.0);
export default rootOf2;
Answer given by Chris G is correct. I would also like to add that there is the difference between two ways you can export your variables or functions, by export and export default.
Imagine having variable in file const myVar = 'someValue';
If you export it from file just with export export { myVar } you would have to import it in the file where you would like to use your variable of function like this: import { myVar } from 'name-of-your-module';
In other case, where you export it with default export default myVar, you can import it without {} - like this: import myVar from 'name-of-your-module'
Export default serves to export a single value or to have a fallback value for our module.

HOC import TypeError: Object(...) is not a function

I just tried to use a simple HOC with react.
Here is the function :
import React from "react"
const withOptions = (WrappedComponent) => {
return class extends React.Component {
render() {
return <WrappedComponent { ...this.props } />
}
}
}
export default withOptions
The problem seems to be in the way i export/import it.
Imported and used in a simple way, it works :
import withOptions from "./Options"
...
class BilanClimatique extends React.Component{
...
}
const StyledBilanClimatique = withStyles(styles)(BilanClimatique)
export default withOptions(StyledBilanClimatique)
But if i use an intermediate file like index.js
import withOptions from "./Options"
export {
withOptions
}
And import it in my component like that
import {
withOptions
} from "./index"
Here is what i get
Can someone help me understand this ?
EDIT :
I found that the component that is using the HOC is imported from the same file as the HOC :
import withOptions from "./Options"
import BilanClimatique from "./BilanClimatique"
export {
withOptions,
BilanClimatique
}
And that causes the problem, but I don't understand why...
Here is a sandbox with the problem https://codesandbox.io/s/r074735yvo
This seems to be a problem with hoisting of 'exports'. From what I can see, the imports get hoisted, but I could not see anything similar for exports.
The flow which causes problem (codesandbox):
App.js:
import { BilanClimatique } from "./components/index";
./components/index.js:
// just using the "re-export" shortcut
export { default as BilanClimatique } from "./BilanClimatique";
export { default as withOptions } from "./Options";
./components/BilanClimatique.js:
import { withOptions } from "./index";
./components/Options.js:
const withOptions = WrappedComponent => {
return ... //snipped code
export default withOptions;
When App.js asks index.js for BilanClimatique, it in turn asks the same index.js for withOptions. But since exports don't seem to be hoisted, index.js has not yet made withOptions available.
How to solve:
Ordered exports:
in ./components/index.js, change the order of exports as per your dependency:
// just using the "re-export" shortcut
export { default as withOptions } from "./Options";
export { default as BilanClimatique } from "./BilanClimatique";
I would not recommend it. It is very fragile.
Use index.js to only expose to outside your namespace. Inside your namespace, rely on explicit imports.
i.e. in ./components/BilanClimatique.js:
import withOptions from "./Options";
If you have a very large codebase, use multiple index.js for exporting your "contracts". Take a look at the codebases of various library authors, I think that is the strategy they take.
I would personally recommend #2 over #3 unless you run into problems with #2.
. doesn't look as a great import path. Try to import from 'index' file.
import {
Logo,
withOptions
} from "./index"

React - How to export a pure stateless component

How can I export a stateless pure dumb component?
If I use class this works:
import React, { Component } from 'react';
export default class Header extends Component {
render(){
return <pre>Header</pre>
}
}
However if I use a pure function I cannot get it to work.
import React, { Component } from 'react';
export default const Header = () => {
return <pre>Header</pre>
}
Am I missing something basic?
ES6 doesn't allow export default const. You must declare the constant first then export it:
const Header = () => {
return <pre>Header</pre>
};
export default Header;
This constraint exists to avoid writting export default a, b, c; that is forbidden: only one variable can be exported as default
Just as a side note. You could technically export default without declaring a variable first.
export default () => (
<pre>Header</pre>
)
you can do it in two ways
const ComponentA = props => {
return <div>{props.header}</div>;
};
export default ComponentA;
2)
export const ComponentA = props => {
return <div>{props.header}</div>;
};
if we use default to export then we import like this
import ComponentA from '../shared/componentA'
if we don't use default to export then we import like this
import { ComponentA } from '../shared/componentA'
You can also use a function declaration instead of assignment:
export default function Header() {
return <pre>Header</pre>
}
In your example, you already use curly brackets and return so this is apparently matching with your needs with no compromise.

Categories