How to call React class component from normal JavaScript function? - javascript

I wanted to call the React class component from the JavaScript function which is defined in the another file. Here React Class component having the JSX syntax. Is it possible ?
This is my React Class component defined in the file Example.js
class Example extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
This is my normal JavaScript function defined in the file Normal.js . From this function I wanted to call my React class component. How to call ?
function Calling() {
//From Here I wanted to call React Class component (Example)
}

Related

React functional (hooks) component in parent class component

I have a quite big React component SearchProvider written as a class and a UI component InputRange that I wrote as functional component using Hooks.
ATM I am getting the error "Invalid hook call. Hooks can only be called inside of the body of a function component."
Can I use the hook component as a child of the class component?
import { InputRange } from 'react-components';
class SearchProvider extends Component {
render() {
return <Fragment>
<InputRange />
{this.props.children}
</Fragment>;
}
function InputRange(props) {
...
useEffect(_ => { ...});
return <div className="input-range"></div>;
}
I answer my own question. The problem was duplicated react and not directly related to hooks. See https://reactjs.org/warnings/invalid-hook-call-warning.html#duplicate-react
I had to declare react and react-dom in the UI component as peerDependencies. This solves the problem.

Pass React Props to a Separate JS File

I'm trying to pass props for width from a parent component to a child JS file, but cannot seem to get the props value in the child JS file. The parent is the following:
import React from 'react';
import Child from './Child';
export default class Home extends React.Component {
state = {
width: 1000
}
render(){
return(
<div>
<Child width={this.width} />
</div>
);
}
}
The separate child JS file is the following:
import React from 'react';
const svgWidth = 650, // Load prop here
svgHeight = 340;
What I've tried is the following but is not working for me:
import React from 'react';
const Child = (props) => {
console.log({props.width}); // Getting an error that ',' is expected
return {props.width};
}
Can someone please help me with passing the width value from ?
Change to the following, as you should access state through this.state, like so:
<Child width={this.state.width} />
Either use the prop drilling, hence pass the values from parent to child as a prop.
But exact answer to your question will be :
create a blank object in separate js file and export it and then in componentDidMount populate that object with the props which you want to save. Next time when ever you will use that object anywhere in normal js file you will get the props.
If you intend to pass props to a child component, then I would start with the following:
import React from 'react';
import Child from './Child';
export default class Home extends React.Component {
constructor(props) { // don't forget to add a constructor
super(props); // also required
this.state = {
width: 1000
}
}
render(){
// to pass state use {this.state}
return(
<div>
<Child width={this.state.width} />
</div>
);
}
}
However, if that is not the case and instead you want to export state to a separate js file (that may not even be a React component), then you may have to look at export syntax. I am struggling with a similar problem right now and I already tried what Vikash Kumar suggested without success. This is explained on this question but I was not successful with that approach either: export function inside react component or access state in same file outside of component

How to pass a class extending React.Component as a property to render it (using babel)?

This issue is only reproducable in babel (using babel-runtime-6.26.0).
Having the following structure
class Foo extends React.Component {
// ...
}
class Bar extends React.Component {
render() {
return this.props.component();
}
}
// somewhere:
<Bar component={Foo} />
worked and works for me in general, but when switching to babel I get the error message:
TypeError: Cannot call a class as a function in (classCallCheck.js:7). I've read that this is spec compliant behavior, but it does work outside of the babel environment.
Btw, if I use functional stateless components it works, of course. But I can't guarantee that the consumer of my lib is providing such a component and not a class based one.
How can I approach this using babel?
Is there a different pattern to use to pass components via properties? I believe it's common practice to pass in classes/class constructors via props to components.
A component can be either a function or a class. And ES6 classes cannot be called without new, at least the ones that are spec-compliant (this includes native and Babel classes).
This is not a problem since components shouldn't be instantiated manually. Both function and class components will be properly handled by ReactDOM.render:
class Bar extends React.Component {
render() {
const Component = this.props.component;
return <Component/>;
}
}
Try using React.createElement(this.props.component, props) instead.
Here's a working example:
class Foo extends React.Component {
render() { return "Foo" }
}
class Bar extends React.Component {
render() {
return React.createElement(this.props.component, {})
}
}
ReactDOM.render(
<Bar component={Foo} />,
document.getElementById('root')
);
https://codepen.io/anon/pen/QQGQYZ

Self invoking function in react js ? (as in regular javascript)

I want to invoke the function good without calling it from a event. It should run as soon as page opened just like in the self invoking javascript function.
Here is an example
import React from 'react';
class App extends React.Component {
good(){
console.log('I was triggered during good')
}
render() {
console.log('I was triggered during render')
return(
<div>
good();
</div>
);
}
}
export default App;
Few Points:
1. You need to use this keyword to call any function from any other function.
2. To put js code inside JSX, we need to use {}.
Write it like this:
import React from 'react';
class App extends React.Component {
good(){
console.log('I was triggered during good')
return <div> Hello </div>
}
render() {
console.log('I was triggered during render')
return(
<div>
{this.good()}
</div>
);
}
}
Check React DOC: https://facebook.github.io/react/docs/introducing-jsx.html
Check these answers for more details:
How does the "this" keyword work?
What do curly braces mean in JSX (React)?
You can also use lifecycle methods as componentDidMount(){} or componentWillMount(){}.
componentWillMount will be triggered before mounting of component and componentDidMount() will be triggered after component has been mounted.

ESLint - Component should be written as a pure function (react prefer/stateless function)

ESLint is giving me this error on a react project.
Component should be written as a pure function (react prefer/stateless
function)
It points to the first line of the component.
export class myComponent extends React.Component {
render() {
return (
//stuff here
);
}
}
How do I get rid of this error?
Two choices.
Temporarily disable warning
(Untested; and there are multiple ways to do this.)
// eslint-disable-next-line react/prefer-stateless-function
export class myComponent extends React.Component {
...
}
Use a pure stateless component
The return value is what will be rendered (e.g., you're basically writing class-based component's render method:
export const myComponent = () => {
return (
// JSX here
)
}
(Or use non-ES6 notation if that's your thing.)
For components like this with no other supporting logic I prefer the implicit return, e.g.,
export MyComponent = () =>
<div>
// Stuff here
</div>
This is a matter of preference. I would say that you should follow React naming conventions, though, and keep all components starting with an upper-case letter.
ESLint may complain about missing parens around a multi-line JSX expressions, so disable that rule or use parens.
If you need props, they're passed in as the argument to the function:
const MyComponent = (props) =>
<div>
<Something someProp={props.foo} />
</div>
export MyComponent
And you can destructure in the parameter as usual for convenience:
const MyComponent = ({ foo }) =>
<div>
<Something someProp={foo} />
</div>
This can make the implicit return a little easier if you were using local vars. You'll get an ESLint warning about missing PropTypes unless you declare them; since it's not a class you cannot simply use static propTypes in the class, they must be attached to the function (which many people prefer anyway).
Add constructor() like:
exports class myComponent extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<div>Hello</div>
);
}
}
Write your component as a stateless function:
export myComponent = () => { //stuff here };
There are actually two styles of defining components in React: Functional components (which are just functions from props to a React component) and class components.
The main difference between them is that class components can have state and lifecycle methods such as componentDidMount, componentDidUpdate, etc.
Whenever you don't need state of lifecycle methods, you should write your component as a stateless function, as stateless components are in general easier to reason about.
To write a functional component, you write a function that takes a single argument. This argument will receive the component's props. Consequently, you don't use this.props to access the component's props - you just use the function's argument.
If you rely on props, then there is a better (somewhat arguable, as of this writing) way to fix this error without writing out Stateless functions - by writing a PureComponent and using this eslint rule [source]:
"react/prefer-stateless-function": [2, { "ignorePureComponents": true }],
With above rule, the following snippet is valid (since it depends on props)
class Foo extends React.PureComponent {
render() {
return <div>{this.props.foo}</div>;
}
}
React team plans to build optimizations around SFC but they are not there yet. So until that happens, SFCs will not offer any benefits over PureComponents. In fact, they will be slightly worse as they will not prevent wasteful renders.
You will get this error only when your class does not have any life cycle method or constructor.
To solve this either you have to disable the lint property or make it as a pure function or create constructor for the class.
const myComponent = () => {
return (
//stuff here
);
};
export default myComponent;
And in app.js file just import this component as we do for class like
import myComponent from './myComponent.js'
and call as
<myComponent />
It will work for sure.
export class myComponent extends PureComponent {
...
}
If all you're doing is rendering a jsx template, and not declaring state with constructor(props), then you should write your component as a pure function of props, and not use the class keyword to define it.
ex.
export const myComponent = () => (
// jsx goes here
);
you need to add constructor(props)
export class myComponent extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
//stuff here
);
}
}

Categories