Exporting default statement - javascript

I need to understand the export and import statement in React (Might involve the use of HOC)
So I have a higher component known as withclass.js like this
import React from 'react';
const withClass = (WrappedComponent, ClassName) => {
console.log(WrappedComponent)
console.log(ClassName)
return (props) => (
<div className={ClassName}>
<WrappedComponent />
</div>
)
}
export default withClass;
And inside our App.js, we do something like this
import withClass from '../hoc/withclass.js';
import classes from './App.css';
class App extends Component {
//some code here
//------ include render and return
export default withClass(App, classes.App);
Now, In Export statement I understand that he is passing two parameters which our withClass function requires as parameters but shouldn't he import something in withclass.js? How does our withclass.js receive those arguments?
Also, how does our return function (in withclass.js) get access to props here? (for example we passed props as an argument to our return function in withclass.js)?

I wasn't quite clear what you are asking for but regarding passing the argument you can do something like shown below. If I can get a little more explanation, I will update my answer.
import withClass from '../hoc/withclass.js';
class App extends Component {
//some code here
//------
return (
<Aux>
<button onClick={this.showPersonTrueHandler}>Show Persons </button>
<Ccockpit
coatiitle = {this.props.title}
cocPersonState = {this.state.showPerson}
cocperson = {this.state.person.length}
toggler = {this.togglerPersonHandler} />
{person}
</Aux>
)
}
}
export default withClass((parameter1, parameter2)=>{
//perform any action here...
})(App);

Related

Pass a function from a Functional Component to a Class based Component

Parent Component is like below
import React, { useState } from "react";
import EntityDefinition from "./EntityDefinition";
export default function EntitySelection(props) {
const testFun = () => {
console.log("Function activated");
};
return (
<>
<div>
<EntityDefinition
testFun={testFun}
/>{/**Calling a Class based Component*/}
</div>
</>
);
}
Class based Component (Child)
import React from "react";
import { ComboBox, DropdownOption, Button } from "react-widgets";
import axios from "axios";
export default class EntityDefinition extends React.Component {
render() {
return (
<React.Fragment>
<div>
{" "}
<Button onClick={this.testFun}>Close</Button>{" "} {/*/Calling the function passed*/}
</div>
</React.Fragment>
);
}
}
but when i clicked the button the testFun function is not being called.
i tried something like onClick={this.state.testFun} , onClick={testFun}
but nothing is happening.
can someone point what am i doing wrong here.
testFun is a prop. So use this.props.testFun
onClick={this.props.testFun}
testFun is a prop, and you are using the ES6 class component, and it receives the props as a props object, so you can try accessing it as below
onClick={this.props.testFun}
You need to refer to props passed to a class based components using this.props from inside the class based components:
Docs
In your case, you should change the onClick listener to this:
<Button onClick={this.props.testFun}>

Can someone explain to me how props is being stored in this component for React Javascript

I'm pretty sure I'm just 100% missing the point on this as I'm new to React and Javascript but.
When I call another component in my main what is exactly happening with props in these two pieces of code? What is table={table} shouldn't we be calling it props? and then when I pass props to my other component why is it being stored as a const with the point of it being props doesn't it already have those values?
import RecordsGetter from './RecordsGetter'
function MainController() {
const base = useBase();
console.log("The name of the base is: ", base);
const tables = base.tables;
console.log("The name of the tables are: ", tables);
return (
<div>
{tables.map((table) => {
return (
<div>
<br />
<div>{table.name}</div>
<div>{table.id}</div>
<div>{table.description}</div>
<RecordsGetter table={table}/>
</div>
);
})}
</div>
);
}
export default MainController;
import React from 'react';
import {useBase} from '#airtable/blocks/ui'
export default function RecordsGetter (props) {
const {
table
} = props;
const records = useRecords(table);
console.log('records', records);
return (<div></div>)
}
props enable you to pass variables from one to another component down the component tree.
<RecordsGetter table={table}/>
ur passing the recrodsgetter data to another component which then can be read by another component. props can be anything from integers over objects to arrays. Props are read-only. In a functional stateless component, the props are received in the function signature as arguments:
for example:
import React, { Component } from 'react';
class App extends Component {
render() {
const greeting = 'Welcome to React';
return (
<div>
<Greeting greeting={greeting} />
</div>
);
}
}
const Greeting = props => <h1>{props.greeting}</h1>;
export default App;
this is the same thing as
import React, { Component } from 'react';
class App extends Component {
render() {
const greeting = 'Welcome to React';
return (
<div>
<Greeting greeting={greeting} />
</div>
);
}
}
class Greeting extends Component {
render() {
return <h1>{this.props.greeting}</h1>;
}
}
export default App;
the result output would be the same in both cases. we are passing down the parameters of greeting to another component. Which in your case you are passing the table params

componentDidMount not called, its not working at all it seems

I tried many things. Same code is working in my other project but not in the current one
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import getProductCategories from '../../redux/actions/productCategoryAction'
import "./ProductCategory.css"
export class ProductCategory extends Component {
static propTypes = {
productCategories: PropTypes.array.isRequired
}
componentDidMount() {
console.log('Mounted!');
this.props.getProductCategories();
}
render() {
return (
<div className="main-card-body">
<div className="main-card-container">
{this.props.productCategories.map((pc, i) => {
return (
<div key={i} className="main-card-card" >
<div className="main-card-face main-card-face1">
<div className="main-card-content">
<img src={pc.image} alt={pc.alt} />
</div>
</div>
<div className="main-card-face main-card-face2">
<div className="main-card-content">
<h3> {pc.title}</h3>
<p>{pc.description}</p>
</div>
</div>
</div>
)
})}
</div>
</div>
)
}
}
const mapStateToProps = state => ({
productCategories: state.productCategory.productCategories
})
const mapDispatchToProps = dispatch => {
return {
getProductCategories: () => {
dispatch(getProductCategories())
}
};
};
export default connect(mapStateToProps, mapDispatchToProps)(ProductCategory)
tried without mapDispatchToProps as:
export default connect(mapStateToProps, {getProductCategories})(ProductCategory)
componentDidMount failing without any error, not showing console.log string as well.
Although i crosschecked with each and every means i do have still can't resolve.
enter image description here
Found answer all thanks to Michalis Garganourakis and cubrr
In App.js i was importing this class based component "ProductCategory" with curly braces. importing it without curly braces did the job as i am exporting it as "export default"
Again thanks Michalis Garganourakis and cubrr
Cubrr answered this on the very first go. it took me lot of time to understand this silly thing :D :D
Based on the image you added, the error seems to occur on render function, so the componentDidMount never gets triggered for this exact reason.
Try checking if this.props.productCategories exists before trying to use .map() on it. This should allow render function to run succesfully, and this will then trigger the componentDidMount as per react's lifecycle method order
this.props.productCategories && this.props.productCategories.map((pc, i) ...
Also, try removing the export on your first row, keeping just the export default of your last row where you also make use of connect HOC, like:
class ProductCategory extends Component {
// ...
}
export default connect(mapStateToProps, mapDispatchToProps)(ProductCategory)

Bind an event to the component - React, Redux

I have a Component like this:
class GlobalComponent extends React.Component{
select= (e) => {
this.props.select(); // must be implemented in another component and not parent
};
render(){
return(
<div>
{this.state.data}
<Button onClick={this.select}>Select</Button>
</div>
);
}
}
function mapStateToProps(state) {
return state.data
}
const mapDispatchToProps = (dispatch, props) => ({
select: () => dispatch(select()),
});
export default connect(mapStateToProps, mapDispatchToProps)(GlobalComponent );
I am importing this component in the root of my app - app.js like this:
<GlobalComponent />
The problem is this actionselect. I know I can pass it from global state or parent component with props (for the example):
<GlobalComponent select={this.select} />
or with mapDispatchToProps
, but the problem is that the component is defined only in one place, otherwise I need to import the GlobalComponent in almost all components.
What I want is to import the component once (somewhere in the root) and then somehow in a component that uses GlobalComponent define a function, which will NOT execute select, but implement select and it is only for the click event in the GlobalComponent:
export default class ComponentThatUsesGlobal extends React.Component {
executeWhenGlobalComponentBtnIsClicked = () => {
}
}
Is this possible and is it good approach or it is better just to import the component everywhere ?
I am using and Redux.

Getting "Cannot call a class as a function" in my React Project

I'm trying to add a React map component to my project but run into an error. I'm using Fullstack React's blog post as a reference. I tracked down where the error gets thrown in google_map.js line 83:
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
Here is my map component so far. The page loads just fine (without a map) when I comment out lines 58-60, the last three lines. edit: I made the changes that #Dmitriy Nevzorov suggested and it still gives me the same error.
import React from 'react'
import GoogleApiComponent from 'google-map-react'
export class LocationsContainer extends React.Component {
constructor() {
super()
}
render() {
const style = {
width: '100vw',
height: '100vh'
}
return (
<div style={style}>
<Map google={this.props.google} />
</div>
)
}
}
export class Map extends React.Component {
componentDidUpdate(prevProps, prevState){
if (prevProps.google !== this.props.google){
this.loadMap();
}
}
componentDidMount(){
this.loadMap();
}
loadMap(){
if (this.props && this.props.google){
const {google} = this.props;
const maps = google.maps;
const mapRef = this.refs.map;
const node = ReactDOM.findDOMNode(mapRef);
let zoom = 14;
let lat = 37.774929
let lng = 122.419416
const center = new maps.LatLng(lat, lng);
const mapConfig = Object.assign({}, {
center: center,
zoom: zoom
})
this.map = new maps.Map(node, mapConfig)
}
}
render() {
return (
<div ref='map'>
Loading map...
</div>
)
}
}
export default GoogleApiComponent({
apiKey: MY_API_KEY
})(LocationsContainer)
And here is where this map component gets routed in main.js:
import {render} from 'react-dom';
import React from 'react';
import Artists from './components/Artists'
import { Router, Route, Link, browserHistory } from 'react-router'
import Home from './components/HomePage'
import Gallery from './components/ArtGallery'
import ArtistPage from './components/ArtistPage'
import FavsPage from './components/FavsPage'
import LocationsContainer from './components/Locations'
//Create the route configuration
render((
<Router history={browserHistory}>
<Route path="/" component={Home} />
<Route path="locations" component={LocationsContainer} />
<Route path="artists" component={Artists} />
<Route path="gallery" component={Gallery} />
<Route path="favorites" component={FavsPage} />
<Route path=":artistName" component={ArtistPage} />
</Router>
), document.getElementById('app'))
For me it happened when I forgot to write extends React.Component at the end.
I know it's not exactly what YOU had, but others reading this answer can benefit from this, hopefully.
For me it was because I forgot to use the new keyword when setting up Animated state.
eg:
fadeAnim: Animated.Value(0),
to
fadeAnim: new Animated.Value(0),
would fix it.
Edit from 5 years on with more explanation:
The most likely issue is that you're missing the new keyword somewhere, just like I did above. What this means is you don't even need to be using React to come across this error.
The issue is that in JS you can create classes like so (Example from MDN):
class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
calcArea() {
return this.height * this.width;
}
}
If you wanted to use this class, you need to create a new instance of it like so:
const rect = new Rect(height, width);
The reason for this problem is often you're trying to do a function call to the definition of the class (or something inside the definition), rather than an instance of the class.
Essentially, in code, you're doing this:
Rectangle.calcArea() // incorrect!
when you should be doing
rect.calcArea() // correct!
tl;dr
If you use React Router v4 check your <Route/> component if you indeed use the component prop to pass your class based React component!
More generally: If your class seems ok, check if the code that calls it doesn't try to use it as a function.
Explanation
I got this error because I was using React Router v4 and I accidentally used the render prop instead of the component one in the <Route/> component to pass my component that was a class. This was a problem, because render expects (calls) a function, while component is the one that will work on React components.
So in this code:
<HashRouter>
<Switch>
<Route path="/" render={MyComponent} />
</Switch>
</HashRouter>
The line containing the <Route/> component, should have been written like this:
<Route path="/" component={MyComponent} />
It is a shame, that they don't check it and give a usable error for such and easy to catch mistake.
Happened to me because I used
PropTypes.arrayOf(SomeClass)
instead of
PropTypes.arrayOf(PropTypes.instanceOf(SomeClass))
For me, it was ComponentName.prototype instead of ComponentName.propTypes.
auto suggested by Phpstorm IDE. Hope it will help someone.
You have duplicated export default declaration. The first one get overridden by second one which is actually a function.
I experienced the same issue, it occurred because my ES6 component class was not extending React.Component.
Mostly these issues occur when you miss extending Component from react:
import React, {Component} from 'react'
export default class TimePicker extends Component {
render() {
return();
}
}
For me it was because i used prototype instead of propTypes
class MyComponent extends Component {
render() {
return <div>Test</div>;
}
}
MyComponent.prototype = {
};
it ought to be
MyComponent.propTypes = {
};
Post.proptypes = {
}
to
Post.propTypes = {
}
someone should comment on how to monitor such error in a very precise way.
Two things you can check is,
class Slider extends React.Component {
// Your React Code
}
Slider.propTypes = {
// accessibility: PropTypes.bool,
}
Make sure that you extends React.Component
Use propTypes instead of prototype (as per IDE intellisense)
Looks like there're no single case when this error appears.
Happened to me when I didn't declare constructor in statefull component.
class MyComponent extends Component {
render() {
return <div>Test</div>;
}
}
instead of
class MyComponent extends Component {
constructor(props) {
super(props);
}
render() {
return <div>Test</div>;
}
}
This is a general issue, and doesn't appear in a single case. But, the common problem in all the cases is that you forget to import a specific component (doesn't matter if it's either from a library that you installed or a custom made component that you created):
import {SomeClass} from 'some-library'
When you use it later, without importing it, the compiler thinks it's a function. Therefore, it breaks. This is a common example:
imports
...code...
and then somewhere inside your code
<Image {..some props} />
If you forgot to import the component <Image /> then the compiler will not complain like it does for other imports, but will break when it reaches your code.
In file MyComponent.js
export default class MyComponent extends React.Component {
...
}
I put some function related to that component:
export default class MyComponent extends React.Component {
...
}
export myFunction() {
...
}
and then in another file imported that function:
import myFunction from './MyComponent'
...
myFunction() // => bang! "Cannot call a class as a function"
...
Can you spot the problem?
I forgot the curly braces, and imported MyComponent under name myFunction!
So, the fix was:
import {myFunction} from './MyComponent'
I received this error by making small mistake. My error was exporting the class as a function instead of as a class. At the bottom of my class file I had:
export default InputField();
when it should have been:
export default InputField;
For me, it was because I'd accidentally deleted my render method !
I had a class with a componentWillReceiveProps method I didn't need anymore, immediately preceding a short render method. In my haste removing it, I accidentally removed the entire render method as well.
This was a PAIN to track down, as I was getting console errors pointing at comments in completely irrelevant files as being the "source" of the problem.
I had a similar problem I was calling the render method incorrectly
Gave an error:
render = () => {
...
}
instead of
correct:
render(){
...
}
I had it when I did so :
function foo() (...) export default foo
correctly:
export default () =>(...);
or
const foo = ...
export default foo
For me it happened because I didn't wrap my connect function properly, and tried to export default two components
I faced this error when I imported the wrong class and referred to wrong store while using mobx in react-native.
I faced error in this snippet :
import { inject, Observer } from "mobx-react";
#inject ("counter")
#Observer
After few corrections like as below snippet. I resolved my issue like this way.
import { inject, observer } from "mobx-react";
#inject("counterStore")
#observer
What was actually wrong,I was using the wrong class instead of observer I used Observer and instead of counterStore I used counter. I solved my issue like this way.
I experienced this when writing an import statement wrong while importing a function, rather than a class. If removeMaterial is a function in another module:
Right:
import { removeMaterial } from './ClaimForm';
Wrong:
import removeMaterial from './ClaimForm';
I have also run into this, it is possible you have a javascript error inside of your react component. Make sure if you are using a dependency you are using the new operator on the class to instantiate the new instance. Error will throw if
this.classInstance = Class({})
instead use
this.classInstance = new Class({})
you will see in the error chain in the browser
at ReactCompositeComponentWrapper._constructComponentWithoutOwner
that is the giveaway I believe.
In my case i wrote comment in place of Component by mistake
I just wrote this.
import React, { Component } from 'react';
class Something extends Component{
render() {
return();
}
}
Instead of this.
import React, { Component } from 'react';
class Something extends comment{
render() {
return();
}
}
it's not a big deal but for a beginner like me it's really confusing.
I hope this will be helpfull.
In my case, using JSX a parent component was calling other components without the "<>"
<ComponentA someProp={someCheck ? ComponentX : ComponentY} />
fix
<ComponentA someProp={someCheck ? <ComponentX /> : <ComponentY />} />
Another report here: It didn't work as I exported:
export default compose(
injectIntl,
connect(mapStateToProps)(Onboarding)
);
instead of
export default compose(
injectIntl,
connect(mapStateToProps)
)(Onboarding);
Note the position of the brackets. Both are correct and won't get caught by either a linter or prettier or something similar. Took me a while to track it down.
In my case, I accidentally put component name (Home) as the first argument to connect function while it was supposed to be at the end. duh.
This one -surely- gave me the error:
export default connect(Home)(mapStateToProps, mapDispatchToProps)
But this one worked -surely- fine:
export default connect(mapStateToProps, mapDispatchToProps)(Home)
This occured when I accidentally named my render function incorrectly:
import React from 'react';
export class MyComponent extends React.Component {
noCalledRender() {
return (
<div>
Hello, world!
</div>
);
}
}
My instance of this error was simply caused because my class did not have a proper render method.
Actually all the problem redux connect. solutions:
Correct:
export default connect(mapStateToProps, mapDispatchToProps)(PageName)
Wrong & Bug:
export default connect(PageName)(mapStateToProps, mapDispatchToProps)
In my scenario I was attempting to use hot reloading on a custom hook (not sure why, probably just muscle memory when creating components).
const useCustomHook = () => {
const params = useParams();
return useSelector(
// Do things
);
};
// The next line is what breaks it
export default hot(module)(useCustomHook);
The correct way
const useCustomHook = () => {
const params = useParams();
return useSelector(
// Do things
);
};
export default useCustomHook;
Apparently you can't hot reload hook 😅 😂
In my case I accidentally called objectOf
static propTypes = {
appStore: PropTypes.objectOf(AppStore).isRequired
}
Instead of instanceOf:
static propTypes = {
appStore: PropTypes.instanceOf(AppStore).isRequired
}

Categories