Exporting functional and class components in React - reactjs

I'm using a ES7 React/Redux/GraphQL/React-Native snippets in VS Code and I'm not sure which "type" of export use. If export should be at the class / functional component declaration or at the end of the file.
In the code below, I have 2 class components exports and 3 functional components exports.
Which of these is reccomended?
// ****************************************
// 1. rcc
// ****************************************
import React, { Component } from 'react'
export default class myComponent extends Component {
render() {
return (
<div>
</div>
)
}
}
// ****************************************
// 2. rce
// ****************************************
import React, { Component } from 'react'
class myComponent extends Component {
render() {
return (
<div>
</div>
)
}
}
export default myComponent
// ****************************************
// 3. rfc
// ****************************************
import React from 'react'
export default function myComponent() {
return (
<div>
</div>
)
}
// ****************************************
// 4. rfce
// ****************************************
import React from 'react'
function myComponent() {
return (
<div>
</div>
)
}
export default myComponent
// ****************************************
// 5. rafc
// ****************************************
import React from 'react'
const myComponent = () => {
return (
<div>
</div>
)
}
export default myComponent
My second question is about functional components - It is better (recommended) to write a functional component as an arrow function or classical function declaration?
Thanks a lot!

Dan Abramov said in his tweet:
JS tip: no matter which export style you prefer (default or named) or
which function style you use (arrow or declaration), make sure your
functions have names! Especially important for React components to
show up named in DevTools and warnings.
And, between using rce and rcc for exporting class components: It's up to you to decide, however, as in CRA documentation rce is used:
import React, { Component } from 'react';
import Button from './Button'; // Import a component from another file
class DangerButton extends Component {
render() {
return <Button color="red" />;
}
}
export default DangerButton;
With this style, you can use HOCs easily, for this example we want to warp our class component into a Higher Order Component provided by a library:
import { injectIntl} from "react-intl";
class Button extends React.Component {
render() {
const intl = this.props.intl;
const title = intl.formatMessage({
id: "button.title",
defaultMessage: "Hello!"
});
return <Button title={title}>...</Button>;
}
}
export default injectIntl(Button);
And between using the Functional components vs Class components: Please refer to the documentation, functional components are easier to write and to test, and now with React's useState hook you can use state in your functional components. For class components read React.Component documentation.

if you want to export multiple component in a file then you have to use only export ComponentName (without default).
then you can import as
import {ComponentA,ComponentB,...} from '../directory'
the other case is that you can export only one component in a file as
export default Class extends ........{} //
or
export default Class; // at the end of file
Both are same.
and you can import with any name
import Class from '../directory'

Related

warning : is defined but never used

I created a jsxUses.js file in the components folder, but when I import it in App.js its shows warning: 'jsxUses' is defined but never used
//This is App.js file
import React, { Component } from 'react';
import './App.css';
import jsxuses from './components/jsxUses';
class App extends Component{
render() {
return (
<div className="App">
<jsxuses/>
</div>
);
}
}
export default App;
and this is jsxUses.js file
import React from 'react'
const jsxuses = () => {
return (
<div>
<h1> Hey there!</h1>
</div>
);
}
export default jsxuses;
React Element should be PascalCased. So it should be
import JsxUses from './components/jsxUses';
...
<JsxUses />
Change your jsxUses.js as:
...
const JsxUses = () => {
...
export default JsxUses;
And your App.js as:
import JsxUses from './components/jsxUses';
...
<JsxUses />
React file structure naming is unopinionated but React elements should be PascalCase for React to know whether or not you're using a function, class or an HTMLelementPascalCased.
Look for more here: Is there an official style guide or naming convention for React based projects?
Hope this helps!
Actually you should avoid using small latter for custom tags.
so you should do
const JsxUses = () => {
...
}
export default JsxUses
and
import JsxUses from './components/jsxUses';
or if you want to write like -
const jsxuses = () => {
...
}
export default jsxuses
then you should import it like
import { default as JsxUses } from './components/jsxUses'
Well, Use import JsxUses from './components/JsxUses'; React component name should be PascalCase.

Context data does not get passed into nested component: React+Typescript+ContextAPI

I am using context API to avoid prop drilling across the components. I have a component which has two popup modal's(components). When I am trying to fetch the context data within Enclosing component data, but within the modal I would not get. If I pass again pass this context data as a props to these modal's and then if I fetch this props accessor then I am able to fetch. Where am I going wrong? If I am not wrong, this context API does not depend on the nested levels, can someone help me here?
CacheContext.tsx
import React from "react";
const context = React.createContext(null);
export default context;
ContextProvider.tsx
import React, {Component} from "react";
import context from './CacheContext';
var TinyCache = require( 'tinycache' );
var cache = new TinyCache();
class ContextProvider extends Component {
render() {
return (
<context.Provider value={cache}>
{this.props.children}
</context.Provider>
);
}
}
export default ContextProvider;
ComponentA.tsx
import * as React from "react";
import context from "../Utilities/CacheContext";
export default class ComponentA extends React.Component<{}, {}> {
componentDidMount() {
console.log(this.context) // I am able to the data here
}
render(){
return(
<Modal1/> //if I pass this as context={this.context} then it works
<Modal2/>
)
}
}
ComponentA.contextType=context;
Modal1.tsx
import * as React from "react";
import context from "../Utilities/CacheContext";
export default class Modal1 extends React.Component<{}, {}> {
componentDidMount() {
console.log(this.context) // I am unable able to the data here , If I use this.props.context and pass the context as props then I am able to get
}
render(){
return(
//some content
)
}
}
Modal1.contextType=context;
In the new context API ( https://reactjs.org/docs/context.html#api ) You should use the context.Consumer component using a function as children:
<context.Consumer>
{cache => console.log(cache)}
</context.Consumer>
If you need the cache in componentDidMount, pass the cache to a sub-component like this:
// render:
<context.Consumer>
{cache => <SubComponent cache={cache}/>}
</context.Consumer>
// SubComponent:
class SubComponent {
componentDidMount() {
console.log(this.props.cache);
}
}

Component is declared but never used

I keep getting this weird message and React isnĀ“t rendering my component. I am pretty sure I am rendering and importing it correctly:
Container:
import searchBar from "./searchBar";
class ItemList extends Component {
render() {
return (
<searchBar/>
);
}
}
searchBar
import React, { Component } from 'react';
const searchBar = () => {
return <div>ssuhsuhuhsususu</div>;
}
export default searchBar
Change to
const SearchBar = () => {
return <div>ssuhsuhuhsususu</div>;
}
export default SearchBar;
I you give name in small caps it will be considered as HTML tag such as
<p>, <div>
So your component should always be starting with CAPS.
If you want to use component which name start with lowercase then use can use following tips:
Just assign it to capitalised variable before using it.
import searchBar from "./searchBar";
const Foo = searchBar;
<Foo/>
Full Code:
import searchBar from "./searchBar";
const Foo = searchBar;
class ItemList extends Component {
render() {
return (
<Foo/>
);
}
}

How to avoid repeating interface in Typescript React

It's my first app I try to build using Typescript. I want to keep styles and components in separate files to make the code more descriptive and clear. Project will consist of dozens of components and I'll use props to call the classes. Each component will look more or less like this:
import * as React from 'react'
import withStyles from "#material-ui/core/styles/withStyles"
import { LandingPageStyles } from "./landing-page-styles"
interface LandingPageProps {
classes: any
}
class LandingPage extends React.Component<LandingPageProps> {
get classes() {
return this.props.classes;
}
render() {
return(
<div className={this.classes.mainPage}>
Hello Typescript
</div>
)
}
}
export default withStyles(LandingPageStyles)(LandingPage)
And simplified styles module :
import { createStyles } from "#material-ui/core";
export const LandingPageStyles = () => createStyles({
mainPage: {
textAlign: "center",
minHeight: "100vh",
}
})
In every component I want to have the classes props with type of any. Is there a way to avoid declaring interface for each component? It works now but I don't like my current solution beacuse of repetition the same code in every single component.
The proper way to do it is as bellow. Material-ui expose WithStyles interface that you can inherit to include classes props. The main advantage is that you IDE will handle autocompletion for the defined jss class. But anyway Typescript is more verbose than Javacript. With React you often have to repeat obvious things.
import * as React from 'react'
import {withStyles, WithStyles} from "#material-ui/core"
import { LandingPageStyles } from "./landing-page-styles"
interface LandingPageProps extends WithStyles<typeof LandingPageStyles> {
}
class LandingPage extends React.Component<LandingPageProps> {
get classes() {
return this.props.classes;
}
render() {
return(
<div className={this.classes.mainPage}>
Hello Typescript
</div>
)
}
}
export default withStyles(LandingPageStyles)(LandingPage)
The best solution is to declare interface which extends WithStyles . So in component there is need to declare:
import * as React from 'react'
import withStyles, { WithStyles } from "#material-ui/core/styles/withStyles"
import { LandingPageStyles } from "./landing-page-styles"
interface LandingPageProps extends WithStyles<typeof LandingPageStyles>{
}
class LandingPage extends React.Component<LandingPageProps> {
get classes() {
return this.props.classes;
}
render() {
return(
<div className={this.classes.mainPage}>
Hello Typescript
</div>
)
}
}
export default withStyles(LandingPageStyles)(LandingPage)

Component in React version 16

The following is giving me an error in React v16.0. The error I'm getting is:
TypeError: Cannot read property 'createElement' of undefined
import { React, Component } from 'react';
class MyComponent extends Component {
render() {
return(
<div>Hello World!</div>
);
};
};
If I change it to the following, it works.
import React from 'react';
class MyComponent extends React.Component {
// Omitted for brevity
}
I'm aware of some changes from v15.x to 16.x but I'm not clear about this one.
Your import needs to be the following: import React, { Component } from 'react';
React is your standard default export as before but Component is a named export.

Resources