How to implement a class controller option in Flare React package - javascript

Update: I added a codesanbox at the bottom of this with a more detailed explanation of what I need done.
So I don't quite understand how classes work in React, I am new to react and have used useState a little bit, but never have know what to do with a class. I am using this react package that has an example of how to use a controller to make you animation interactive built with flare now called rive. https://github.com/2d-inc/Flare-React#readme
What I want to achieve is to either run a different animation, or the same animation again when I hover over canvas element that is generated. I can create a second animation in flate(rive) that would still output in the same .flr file and I should then be able to reference it in the controller and run it on hover, just stuck on how to even do that part, or even get this controller to work. One thing to note is I can get the animation to run fine without the controller.
In the docs they have this example code
class PenguinController extends FlareComponent.Controller
{
constructor()
{
super();
this._MusicWalk = null;
this._Walk = null;
this._WalkTime = 0;
}
initialize(artboard)
{
this._MusicWalk = artboard.getAnimation("music_walk");
this._Walk = artboard.getAnimation("walk");
}
advance(artboard, elapsed)
{
// advance the walk time
this._WalkTime += elapsed;
const { _MusicWalk: musicWalk, _Walk: walk, _WalkTime: walkTime } = this;
// mix the two animations together by applying one and then the other (note that order matters).
walk.apply(walkTime % walk.duration, artboard, 1.0);
// if you want to slowly disable the head bobbing (musicWalk animation) you could ramp down the
// final argument (the mix argument) to 0.0 over some time. For now we're mixing at full strength.
musicWalk.apply(walkTime % musicWalk.duration, artboard, 1.0);
// keep rendering
return true;
}
}
First of all what is a constructor? what does super mean? then what are they defining in the constructor, is that some state, how do I determine what to define here?
For the initialized I assume I match it to the state above, and get the animation by the name I named it in flare(rive)
The advance part I don't really understand are we setting the animation with this._WalkTime += elapsed; to how long the animation runs? I think I understand the apply section, it is applying a duration to the animation.
Next it has this code
class MyComponent extends React.Component
{
constructor()
{
this.state = { penguinController: new PenguinController() };
}
render()
{
return <FlareComponent controller={this.state.penguinController} /*... more properties here ...*/ />;
}
}
Here is my attempted code currently I get the following error
TypeError: Cannot set property 'state' of undefined
import React from "react"
import PropTypes from "prop-types"
import { useStaticQuery, graphql } from "gatsby"
import FlareComponent from 'flare-react';
import styled from 'styled-components'
import Header from "./header"
import "../sass/index.scss"
const LogoWrapper = styled.div`
width:200px;
height:200px;
`
class AnimationController extends FlareComponent.Controller
{
constructor()
{
super();
this._MusicWalk = null;
}
initialize(artboard)
{
this._MusicWalk = artboard.getAnimation("Wispy Appear");
}
advance(artboard, elapsed)
{
const { _MusicWalk: musicWalk } = this;
musicWalk.apply(musicWalk.duration, artboard, 1.0);
// keep rendering
return true;
}
}
const Layout = ({ children }) => {
const data = useStaticQuery(graphql`
query SiteTitleQuery {
site {
siteMetadata {
title
}
}
}
`)
this.state = { AnimationController: new AnimationController() };
return (
<>
<LogoWrapper>
<FlareComponent width={200} height={200} animationName="Wispy Appear" controller={this.state.AnimationController} file="/wispy-2.flr"/>
</LogoWrapper>
<main className="main-wrapper">{children}</main>
<footer>
© {new Date().getFullYear()}, Built with
{` `}
Gatsby
</footer>
</>
)
}
Layout.propTypes = {
children: PropTypes.node.isRequired,
}
export default Layout
For reference there is a a tutorial on how to make an animation interactive but it's for flutter, but it has some insights into there api https://medium.com/rive/building-a-responsive-house-with-flare-flutter-31af823ba805
Update
Here is my new attempted code after trying to read up on classes in es6, I still need to learn more.
So how do I go about running a second animation on click or hover or any event. The animation runs once now, but I don't know whow to use the controller?
import React from "react"
import Img from 'gatsby-image'
import styled from "styled-components"
import FlareComponent from 'flare-react';
import Layout from "../components/layout"
const LogoWrapper = styled.div`
width:200px;
height:200px;
`
class wispyController extends FlareComponent.Controller
{
constructor()
{
super();
this._Animate = null;
}
initialize(artboard)
{
this._Animate = artboard.getAnimation("Wispy Appear");
}
advance(artboard, elapsed)
{
const { _Animate: animate } = this;
animate.apply(5, artboard, 1.0);
// keep rendering
return true;
}
}
class IndexPage extends React.Component {
constructor()
{
super();
this.state = { wispyController: new wispyController() };
}
render(){
const {data} = this.props;
return(
<Layout>
<LogoWrapper>
<FlareComponent width={200} height={200} animationName="Wispy Appear" controller={this.state.wispyController} file="/Wispy.flr"/>
</LogoWrapper>
{data.allSanityBlogPost.edges.map(({ node: post }) => (
<article key={post.id}>
<h1>{post.name}</h1>
<img src={post.imageGif.asset.url}/>
</article>
))}
</Layout>
)
}
}
export default IndexPage
export const query = graphql`
query IndexQuery {
allSanityBlogPost {
edges {
node {
name
id
imageGif {
asset {
url
}
}
}
}
}
}
`
Ok Hopefully someone can help here, I made a codesandbox so someone can see what I am trying to achieve. There are two animations, on the page you can see the first one which has a controller which should be mixing the two, and then the other two animations on there own. What I want to happen is the first animation run and then the second one to run on hover. HEre is the code sandbox https://codesandbox.io/s/frosty-water-jnj9m

Classes in the context of React can be thought of as classes in most Object Oriented Programming language, they are a blueprint to create an object from. In order to let the language know how and what to do when we create it, it needs a constructor method. This constructor method is calling a special method called super() so that it calls the constructor of the class it is extending from, in this case FlareComponent.Controller
The method advance will be called to add to the captured walk time that the class is keepi track of.
One of the problems is that you are trying to set the state of the component directly instead of using setState https://reactjs.org/docs/react-component.html
I would highly recommend brushing up on React basics before you continue with this, it will really help you get the proper foundation you need.

Related

I made a clock class in JavaScript, but it's not working properly when imported. I can only get the seconds and the interval doesn't seem to work too

import React, { Component } from 'react';
import { Text, View } from 'react-native';
export default class Clock extends Component {
componentDidMount(){
setInterval(() => (
this.setState(
{ curHours : new Date().getHours()}
),
this.setState(
{ curMins : new Date().getMinutes()}
),
this.setState(
{ curSeconds : new Date().getSeconds()}
)
), 1000);
}
state = {curHours:new Date().getHours()};
state = {curMins:new Date().getMinutes()};
state = {curSeconds:new Date().getSeconds()};
renderHours() {
return (
<Text>{'Hours:'}{this.state.curHours}</Text>
);
}
renderMinutes() {
return (
<Text>{'Minutes:'}{this.state.curMinutes}</Text>
);
}
renderSeconds() {
return (
<Text>{'Seconds:'}{this.state.curSeconds}</Text>
);
}
}
-I'm trying to make an app that can keep track of time kinda like a daily planner. So I need to get the current time in real time during app run time. The app is supposed to tell the user that they have failed to accomplish a certain task in a given time for example. I tried exporting the clock.js and using its functions but only the renderSeconds() is working, the others are only showing blanks.
I think functional components will be much simpler to solve this, but it's just my opinion.
Here's a link to an example
When you're defining state three times, only the last one is persisted because you're overwriting the previous variable. In addition, your initial state should be declared in a constructor. Add this to the top of your class
constructor() {
this.state = {
curHours:new Date().getHours(),
curMins:new Date().getMinutes(),
curSeconds:new Date().getSeconds(),
}
}

How to pass a state to multiple other classes in React

I started learning React approx. month ago and I'm very confused about the concept because its still something new to me(compared to my previous work in C++ and C).
To quickly summarize I would like to know what is React's equivalent of C++ return form a function. How would I return value(or values) from a function(in my case class functions/states) and use it in my other components.
I have made an simple script that changes background to simulate RGB light on mouse and I made it so the HSL color mode is applied to the background of the component. I would like to use this on multiple components,icons, etc on my page but it feels like there is a better way than importing all functions in three files making the work triple than requiered.
import React, { Component } from 'react'
import './colorStrip.scss'
class ColorStrip extends Component {
constructor(props) {
super(props)
this.colorHue=10;
this.colorSaturation=100;
this.colorLightness=50;
this.state = {
color:"hsl(0,100%,50%)"
}
this.changeColor(1);
}
changeColor = (speed) => {
this.colorHue+=10*speed;
if(this.colorHue>=360)
this.colorHue=0;
this.setState({
color : "hsl("+this.colorHue+","+this.colorSaturation+"%,"+this.colorLightness+"%)"
})
setTimeout(() => {this.changeColor(speed)},75)
}
render() {
return (
<svg style={{backgroundColor:this.state.color}} className="strip">
</svg>
)
}
}
export default ColorStrip
So I would like to use this.state.color(or this.state.colorHue or any state) in three other SVG components on my page.
I really looked some of the other answers but they were quite complex and requiered multiple returns which was confusing.
There are a couple different options you can use to achieve this.
One would be to move your function that calculates the colour to a higher level component (so one of the parent components), that has the child components you want to pass this state to, and then pass your state down through component props.
class parent extends component {
// your functions to calculate your colour
render () {
return <div>
<ChildComponent colourProp={this.state.color} />
<ChildComponent colourProp={this.state.color} />
<ChildComponent colourProp={this.state.color} />
</div>
}
}
Another option if you need the colour to change based on the child component, is to pass down the function that alters the colour to the child component. So similar to the example above, but you would pass down the colour changing function to the child as well.
<ChildComponent colourProp={this.state.color} changeColour={this.changeColourFunction}/>
Now you can call that function from your child
// Inside child component
this.props.changeColour(params)
And now your parent will change its state, and the new colour will get changed in the parent and passed down to all the children.
Lastly you can try using ReactContext, set it up in a file that's external to all your components and and import it to your components. In your parent component where you pass your initial state, you would use YourContext.Provider and pass your initial state. Then in your children you can use YourContext.Consumer. For more details on this see : https://reactjs.org/docs/context.html
As Jonathan said, you can pass state as props to other components, but only if they are connected. If the svgs you are using are not being rendered in the same file, things will become a little messy. In order to 'fix' this, people use state management tools, such as redux and context API.
Redux, for example, is built based on database design, so you can access the state globally. Tough it is really useful, the environment is not beginners friendly, and I do not advise you learning it until completely grasping react.
Try this way:
import './colorStrip.scss'
class ColorStrip extends Component {
constructor(props) {
super(props)
this.colorHue=10;
this.colorSaturation=100;
this.colorLightness=50;
this.state = {
color:"hsl(0,100%,50%)"
}
this.changeColor(1);
}
changeColor = (speed) => {
this.colorHue+=10*speed;
if(this.colorHue>=360)
this.colorHue=0;
this.setState({
color : "hsl("+this.colorHue+","+this.colorSaturation+"%,"+this.colorLightness+"%)"
})
setTimeout(() => {this.changeColor(speed)},75)
}
render() {
const { color } = this.props;
return (
<svg style={backgroundColor:color} className="strip">
</svg>
)
}
}
export default ColorStrip
I'd suggest creating a Higher-Order Component (HOC) to house the color logic and then you can wrap any component you want with this HOC and the wrapped component will have the logic & data you need.
For example:
import React, { Component } from "react";
function withColor(WrappedComponent) {
return class ComponentWithColor extends Component {
constructor(props) {
super(props);
this.colorHue=10;
this.colorSaturation=100;
this.colorLightness=50;
this.state = {
color:"hsl(0,100%,50%)"
}
this.changeColor(1);
}
changeColor = (speed) => {
this.colorHue+=10*speed;
if(this.colorHue>=360)
this.colorHue=0;
this.setState({
color : "hsl("+this.colorHue+","+this.colorSaturation+"%,"+this.colorLightness+"%)"
})
setTimeout(() => {this.changeColor(speed)},75)
}
render() {
const { color } = this.state;
return <WrappedComponent color={ color } { ...this.props }/>
}
}
}
Then if you define a new component, and you want it to have access to the color prop, just wrap the component class/function in withColor before constructing.
For example:
class MyComponent extends Component {
render() {
const { color } = this.props;
return (
<svg style={backgroundColor:color} className="strip">
</svg>
)
}
}
const MyComponentWithColor = withColor(MyComponent);
// then export & use MyComponentWithColor

Props are undefined on React initialization. Why?

I am creating a VR application with React 360. What I am trying to do is to eventually create an application as shown here Facebook VR multi surface example. I am taking the code for that example and am trying to fit it into my application. However I'm having a problem with the following initialization of my React components.
I have the following react-360 application with the following code index.js
import React from 'react';
import connect from './Store';
import {
asset,
AppRegistry,
StyleSheet,
Text,
View,
VrButton,
} from 'react-360';
import Entity from 'Entity';
const ModelView = props => {
*********** Problem **************
Why are my props undefined if I am declaring it in the wrapper?
**********************************
return (
<Entity
style={{transform: [{scaleX: 1.25}, {scaleY: 1.25}]}}
source={{obj: asset(`${props.planetName}.obj`), mtl: asset(`${props.planetName}.mtl`)}}
/>
);
};
const ConnectedModelView = connect(ModelView);
export default ConnectedModelView;
AppRegistry.registerComponent('ModelView', () => ModelView);
From the code above, my props for the ModelView should not be undefined. On initialization, it should have the value of earth.
The props are supposed to be initialized in Store.js. Here is the code below:
import React from 'react';
const State = {
planetName: 'earth'
};
const listeners = new Set();
export default function connect(Component) {
return class Wrapper extends React.Component {
state = {
planetName: State.planetName
};
_listener = () => {
this.setState({
planetName: State.planetName
});
};
componentDidMount() {
listeners.add(this._listener);
}
componentWillUnmount() {
listeners.delete(this._listener);
}
render() {
return (
<Component
{...this.props}
planetName={this.state.planetName}
/>
);
}
};
}
Taking a page from the facebook code, what I am doing is initializing model view via Store.connect method. This method creates a wrapper around ModelView where I am setting the props via State.planetName. However, I keep getting undefined and I don't know why. I've hardcoded every part of the code which has State.planetName to the value of earth and it still is undefined. The props are not being set to the value I want and I'm not sure why. Can someone out there assist me with why this might be the case? I would appreciate the help.
It looks like you're rendering the ModelView and not the ConnectedModelView.

React/Redux Carousel

So I am creating my own site for my resume and have run up against an issue I'm not exactly sure how to solve. I am using React and Redux, the issue comes up that what I want is to display small little projects in a carousel type format using react with proper redux integrated in. Currently my file structure looks like:
src/
actions/
index.js
components/
App.js
NavBar.js
Projects.js
projects/
Project1/
Project2/
containers/
Main.js
reducers/
index.js
projects.js
I am not sure exactly how to accomplish what I want, I have searched for a good solution, but haven't really come across anything yet. I am still relatively new to react. What I don't want is to display one project, scroll down display the next, scroll some more... What I have tried is:
let components = [{TicTacToe}, {}];
let index = 0;
export default class Projects extends React.Component {
constructor(props) {
super(props);
this.state = {
component: components[0]
};
}
renderProject(i)
{
this.setState({component: components[i]});
}
backRotate()
{
index--;
if(index < 0)
{
index = components.length - 1;
}
this.renderProject(index);
}
forwardRotate()
{
index++;
if(index >= components.length)
{
index = 0;
}
this.renderProject(index);
}
render() {
return(
<div>
<button onClick='backRotate'>Back</button>
<div class='carousel-container'>
<this.state.component />
</div>
<button onClick='forwardRotate'>Next</button>
</div>
) }
}
I originally thought this would work, but it does break. I am currently running through App.js in my components folder adding the NavBar component and then adding the Main.js container. The reason for this container was the fact that I need a back and forward button to rotate through each project just like a carousel of images. I have considered adding all components and then just hiding and revealing, but this seems like a needless waste of resources and that there should be a better way to accomplish this.
Is there a way to replace a component on a button click? Completely remove the original component and add the new component in? If so, how do I also accomplish this using redux? Currently my projects reducer is just a place holder.
First of all, it breaks because the componentsarray contains objects, and React can't have that.
A valid React element is either a node (HTMLElement, React Component, text or number) or an array of nodes.
If you just want to keep React components in a collection and be able to select which is displayed, first you have to remove the braces in the components array, like so:
let components = [TicTacToe, AnotherComponent];
And you will also need to fix your backRotateand forwardRotate handlers. They can't be string like in html (note the braces instead of quotes):
<button onClick={this.backRotate}>Back</button>
<button onClick={this.forwardRotate}>Next</button>
...and must be bound to your component instance. A way to bind them is to use the Function.prototype.bind method. It should be done in the constructor:
constructor(props) {
super(props);
this.backRotate = this.backRotate.bind(this);
this.forwardRotate= this.forwardRotate.bind(this);
}
Without binding this would not be a reference to your component instance and calling this within the handlers would definitely fail.
TicTacToe and AnotherComponent must be classes extending React.Component or React.PureComponent, or must be pure functional components of props.
Also, its clearer and may be more supported to declare a capitalized variable containing the component:
render() {
const Comp = this.state.component;
return (
<div>
<button onClick={this.backRotate}>Back</button>
<div class='carousel-container'>
<Comp />
</div>
<button onClick={this.forwardRotate}>Next</button>
</div>
);
}
Finally, you should make index a state of your component (it's changed with the controls of the component) and components a prop (it does not change within the component).
Instead of setting the current component in state you will set the current component index:
import React from 'react':
import PropTypes from 'prop-types';
import { TicTacToe, AnotherComponent } from 'path/to/named/imports/TicTacToeAndAnotherComponent';
export default class Projects extends React.Component {
static propTypes = {
components: PropTypes.any,
}
static defaultProps = {
components: [TicTacToe, AnotherComponent],
}
constructor(props) {
super(props);
this.state = {
index: 0,
};
this.backRotate = this.backRotate.bind(this);
this.forwardRotate= this.forwardRotate.bind(this);
}
backRotate() {
const { components } = this.props;
const { index } = this.state;
if(index - 1 < 0) {
this.setState(() => ({ index: components.length - 1 }));
} else {
this.setState(() => ({ index: index - 1 }));
}
}
forwardRotate() {
const { components } = this.props;
const { index } = this.state;
if(index >= components.length) {
this.setState(() => ({ index: 0 }));
} else {
this.setState(() => ({ index: index + 1 }));
}
}
render() {
const Comp = this.props.components[this.state.index];
return (
<div>
<button onClick={this.backRotate}>Back</button>
<div class='carousel-container'>
<Comp />
</div>
<button onClick={this.forwardRotate}>Next</button>
</div>
);
}
}
Either way Redux won't help you with that.
The purpose of Redux is mainly to provide a single source of data (single source of truth), provide actions and reducers to mutate this data, and notify components registered to listen to store updates. Weither you connect your carousel to the store or not isn't really relevant to resolve your iisue.

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