React component without extend React Component class - reactjs

I see in some source code, the author wrote a component like this:
import React from 'react';
export const Login = () => (
<div>
<h4>Hello World</h4>
</div>
);
export default Login;
The thing I don't know is:
How react understand this is a react component by only using import
How can I add another callback method, such as viewDidMount ... I have added in code block but it compiles fail.
thanks

This is functional stateless component. It is for simple components.
You also can add component property types like this:
export const Login = () => (
<div>
<h4>Hello World</h4>
</div>
);
Login.propTypes = {
username: React.PropTypes.string.isRequired,
}
You can add callback like this:
// this place to define callback is more effective
const onClick = e => (...)
const Login = props => {
// or define here if you need access to props in onClick
const onClick = e => (...)
return <button onClick={onClick}>Submit</button>
}

React "knows" that the code you wrote is a React Component because of transpilation. Transpilation is a process that occurs during build time where your code is changed from the code you wrote into something else.
In the case of React and JSX, your code turns into
export const Login = () => (
React.createElement('div', {},
React.createElement('h4', {}, 'Hello World')
);
);
The angle brackets (<) are syntactic sugar for React.createElement and people use the angle brackets because they are simpler to use and type.

Related

Change function components method using forwardRef

I am trying to do:
Change child state as in this tutorial: Change child state from parent
Tutorial uses class component, I've tried to use function components.It gives an error like "Function components don't have instances so they can't have refs"
So I used forwardRef (for the first time) according to a stackoverflow answer here
Code:
import React,{useRef,forwardRef, useEffect} from "react";
const Component = (props) => {
function sayHello(){
console.log("hello")
}
return <h1>{props.children}</h1>
}
const ForwardComponent = forwardRef((props,ref)=> (<Component ref={ref}> {props.children} </Component>))
export default function App() {
const hello = useRef()
useEffect(()=>{
hello.current.sayHello()
})
return (
<div>
<ForwardComponent ref={hello}>Hello</ForwardComponent>
</div>
);
}
note: I could use context api or redux here, but I believe it should be simpler in my use case. Also I get to learn something new

React Hook "useState" is called in function "app" which is neither a React function component or a custom React Hook function

I'm trying to use react hooks for a simple problem
const [personState,setPersonState] = useState({ DefinedObject });
with following dependencies.
"dependencies": {
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-scripts": "3.0.0"
}
but I'm still getting the following error:
./src/App.js
Line 7:
React Hook "useState" is called in function
"app" which is neither a React function component or a custom React
Hook function react-hooks/rules-of-hooks
Line 39:
'state' is not defined
no-undef
Search for the keywords to learn more about each error.
Component code is below:
import React, {useState} from 'react';
import './App.css';
import Person from './Person/Person';
const app = props => {
const [personState, setPersonSate] = useState({ person:[ {name:'bishnu',age:'32'}, {name:'rasmi',age:'27'}, {name:'fretbox',age:'4'} ], });
return (
<div className="App">
<h2>This is react</h2>
<Person name={personState.person[1].name} age="27"></Person>
<Person name={personState.person[2].name} age="4"></Person>
</div> );
};
export default app;
Person component
import React from 'react';
const person = props => {
return(
<div>
<h3>i am {props.name}</h3>
<p>i am {props.age} years old</p>
<p>{props.children}</p>
</div>
)
};
export default person;
Try to capitalize 'app' like
const App = props => {...}
export default App;
In React, components need to be capitalized, and custom hooks need to start with use.
I feel like we are doing the same course in Udemy.
If so, just capitalize the
const app
To
const App
Do as well as for the
export default app
To
export default App
It works well for me.
As far as I know a linter is included into the this package. And it requires you componend should begin from Capital character.
Please check it.
However as for me it's sad.
Use first letter capital in the function name.
function App(){}
React components (both functional as well as class) must begin with a capital letter. Like
const App=(props)=><div>Hey</div>
class App extends React.Component{
render(){
return <div>Hey</div>
}
}
React identifies user-defined components by following this semantic. React's JSX transpiles to React.createElement function which returns an object representation of the dom node. The type property of this object tells whether it is a user-defined component or a dom element like div. Therefore it is important to follow this semantics
Since useState hook can only be used inside the functional component(or a custom hook) this is the reason why you are getting the error because react is not able to identify it as a user-defined component in the first place.
useState can also be used inside the custom hooks which is used for the reusability and the abstraction of logic. So according to the rules of hooks, the name of a custom hook must begin with a "use" prefix and must be in a camelCase
Use const App instead of const app
Just try to capitalize your App name
const App = props => {...}
export default App;
You are getting this error: "React Hook "useState" is called in function "App" which is neither a React function component or a custom React Hook function"
Solution: You basically need to Capitalize the function.
For example:
const Helper =()=>{}
function Helper2(){}
I had the same issue. turns out that Capitalizing the "A" in "App" was the issue.
Also, if you do export: export default App; make sure you export the same name "App" as well.
the First character of your function should be an Uppercase
Components should start with capital letters. Also remember to change the first letter in the line to export!
Do you have the right import ?
import React, { useState } from 'react';
function name must start with a capital letter
For ex:
const App = props => {
}
not const app
React components names should be capitalized and custom hooks functions should start with the use keyword to identify as a react hook function.
So, capitalize your app components to App
your code
import React, {useState} from 'react';
import './App.css';
import Person from './Person/Person';
const app = props => {
const [personState, setPersonSate] = useState({ person:[ {name:'bishnu',age:'32'}, {name:'rasmi',age:'27'}, {name:'fretbox',age:'4'} ], });
return (
<div className="App">
<h2>This is react</h2>
<Person name={personState.person[1].name} age="27"></Person>
<Person name={personState.person[2].name} age="4"></Person>
</div> );
};
export default app;
change it by making the function name capital, like this
import React, {useState} from 'react';
import './App.css';
import Person from './Person/Person';
const App = props => {
const [personState, setPersonSate] = useState({ person:[ {name:'bishnu',age:'32'}, {name:'rasmi',age:'27'}, {name:'fretbox',age:'4'} ], });
return (
<div className="App">
<h2>This is react</h2>
<Person name={personState.person[1].name} age="27"></Person>
<Person name={personState.person[2].name} age="4"></Person>
</div> );
};
export default App;
it will work Thank you.
I had the same issue, but not with the App. I had a custom class but used a lowercase letter to start the function name and also received the error.
Changed the first letter of the function name and the export line to CamelCase and error gone.
in my case the end result was something like:
function Document() {
....
}
export default Document;
this solved my problem.
In JSX, the lower-case tag name is considered as html native component.
In order to react recognise the function as React component, need to Capitalized the name.
Capitalized types indicate that the JSX tag is referring to a React component. These tags get compiled into a direct reference to the named variable, so if you use the JSX <Foo /> expression, Foo must be in scope.
https://reactjs.org/docs/jsx-in-depth.html#html-tags-vs.-react-components
The solution is simple, correct "app" and write "App" with the first character in uppercase.
Replace this
export default app;
with this
export default App;
Make function name capital. This works for me.
export default function App() { }
React Hook "useState" is called in function "App" which is neither a React function component or a custom React Hook function"
For the following error , capitalize the component first letter like, and also the export also.
const App = props => {
...}
export default App;
Capitalize the app to App will surely work.
The solution, as Yuki already pointed, is to capitalize the component name. It's important to note that not only the "default" App component needs to be capitalized, but all components:
const Person = () => {return ...};
export default Person;
This is due to eslint-plugin-react-hooks package, specifically isComponentName() function inside RulesOfHooks.js script.
Official explanation from Hooks FAQs:
We provide an ESLint plugin that enforces rules of Hooks to avoid bugs. It assumes that any function starting with ”use” and a capital letter right after it is a Hook. We recognize this heuristic isn’t perfect and there may be some false positives, but without an ecosystem-wide convention there is just no way to make Hooks work well — and longer names will discourage people from either adopting Hooks or following the convention.
First of all, you need to uppercase the FirstLetter of your components, in your case app should be App and person should be Person.
I tried to copy your code in the hope of finding the issue. Since you did not share how you call the App component, I can only see 1 way to result this to an issue.
This is the link in CodeSandbox: Invalid hook call.
Why? Because of the code below which is wrong:
ReactDOM.render(App(), rootElement);
It should have been:
ReactDOM.render(<App />, rootElement);
For more info, you should read Rule of Hooks - React
Hope this helps!
Whenever working with a React functional component, always keep the first letter of the name of the component in Uppercase in order to avoid these React Hooks errors.
In your case, you have named the component app, which should be changed to App, as I said above, to avoid the React Hook error.
Use Capital letter for defining functional component name/ React hooks custom components. "const 'app' should be const 'App'.
App.js
import React, { useState } from 'react';
import { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import Person from './Person/Person';
const App = props => {
const [personState, setPersonState] = useState({
persons : [
{name: 'a', age: '1'},
{name: 'b', age: '2'},
{name: 'c', age: '3'}
]
});
return (
<div>
<Person name = {personState.persons[0].name} age={personState.persons[0].age}> First </Person>
<Person name = {personState.persons[1].name} age={personState.persons[1].age}> Second </Person>
<Person name = {personState.persons[2].name} age={personState.persons[2].age}> Third </Person>
);
};
export default App;
Person.js
import React from 'react';
const person = (props) => {
return (
<div>
<p> My name is {props.name} and my age is {props.age}</p>
<p> My name is {props.name} and my age is {props.age} and {props.children}</p>
<p>{props.children}</p>
</div>
)
};
[ReactHooks] [useState] [ReactJs]
Try to change 'app' name to 'App'
const App = props => {
...
};
export default App;`
Step-1:
Change the file name src/App.js to src/app.js
Step-2:
Click on "Yes" for "Update imports for app.js".
Step-3:
Restart the server again.
import React, { useState } from "react"
const inputTextValue = ({ initialValue }) => {
const [value, setValue] = useState(initialValue);
return {
value,
onChange: (e) => { setValue(e.target.value) }
};
};
export default () => {
const textValue = inputTextValue("");
return (<>
<input {...textValue} />
</>
);
}
/*"Solution I Tired Changed Name of Funtion in Captial "*/
import React, { useState } from "react"
const InputTextValue = ({ initialValue }) => {
const [value, setValue] = useState(initialValue);
return {
value,
onChange: (e) => { setValue(e.target.value) }
};
};
export default () => {
const textValue = InputTextValue("");
return (<>
<input {...textValue} />
</>
);
}
If you are still looking for answer of this question all above stated solution work fine but still i will provide the running/correct code below (edited)
import React, { useState } from 'react';
import './App.css';
import Person from './Person/Person'
const App = props => {
const [personsState, setPersonsState ] = useState({
persons:[
{name: 'Ram', age: 20},
{name: 'Rahul', age: 24},
{name: 'Ramesh', age: 25}
],
otherState: 'Some Other value'
});
const switchNameHandler = () => {
//console.log('Click is working');
//Dont Do THIS: this.state.persons[0].name = 'singh';
setPersonsState({
persons:[
{name: 'Ram',age: 20},
{name: 'Raj', age: 24},
{name: 'yts', age: 30}
]
});
};
return (
<div className="App">
<h1>Nice two one three Hello i am a noob react developer</h1>
<button onClick={switchNameHandler}>Switch Name</button>
<Person name={personsState.persons[0].name} age={personsState.persons[0].age} />
<Person name={personsState.persons[1].name} age={personsState.persons[1].age}> My hobbies are Gaming</Person>
<Person name={personsState.persons[2].name} age={personsState.persons[2].age} />
</div>
);
// return React.createElement('div',{className:'App'}, React.createElement('h1', null, 'Hi learning the basics of react'));
}
export default App;

Define component as constant

Im following a React Native course and at some point the teacher defines a component as constnat using the following code:
const Comment = (props) =>
<Text>{props.text}</Text>
However I dont manage to make it work. I made a snack to just try the component individually and it doesnt work: https://snack.expo.io/S1eKSeV-7
I always get the error Invariant Violation: element type is invalid.
What Im doing wrong?
You are not exporting your component. That is why you get the error because Comment component is undefined.
import React from 'react'
import {Text} from 'react-native'
const Comment = (props) =>
<Text>{props.comment.text}</Text>
export default Comment
This is a functional component. There are two type of components in React: Functional and class components. If you don't need any state or don't use any lifecycle methods in your component you can and should use functional components.
Functional components
const SomeComponent = () => <div>Something</div>;
No need to use an explicit return here since arrow function do this for us if there is one single statement.
With regular function:
function SomeComponent() { return <div>Something</div> };
Class components
class SomeComponent extends React.Component {
state = { foo: "bar" };
someLifeCycleMethod() {
....
}
render() {
return( <div>Something</div>);
}
}
When you don't understand something always refer to official documentation.
The problem you are having is not directly related to component type. As suggested in another answer your component probably is not exported.
This will work:
const Comment = (props) => {
return (
<Text>{props.text}</Text>
);
};

React. how to pass props from onClick to function

I am new to React, I am trying to create an app in which I can click on a button and a function will run countdown timer, but If I pass props from onClick to begin function like this, onClick={begin(props.subject)} the function will run before I click. and if I use onClick with begin without argument, there is no props being passed down. how can I fix that? thanks
import React from 'react';
import SubjectForm from './SubjectForm';
const EditSubject=(props)=>{
return(
<div>
<button onClick={begin}>start</button>
</div>)
};
const begin = (props)=> {
console.log(props.subject)
}
const mapStateToProps=()=>{};
export default connect(mapStateToProps)(EditSubject);
also, is there a way or trick to use a variable inside of begin function from an outside function? so I can make a pause button to pause seInterval in begin function.
You are using functional (stateless) components in this example. You can also use ES6 classes to represent React components, with functions being methods of the class. Then you may make functions like begin in your code as class methods, so they can access class data members like props.
See the code below:
import React from 'react';
import SubjectForm from './SubjectForm';
class EditSubject extends React.Component {
constructor() {
super();
this.begin = this.begin.bind(this);
}
begin() {
console.log(this.props.subject);
}
render() {
return (
<div>
<button onClick={begin}>start</button>
</div>
);
}
};
const mapStateToProps=()=>{};
export default connect(mapStateToProps)(EditSubject);
This is just a best practice if your component has states, and methods. Using functional components like in your example, you may use simply the following:
const EditSubject = (props) => {
return (
<div>
<button
onClick={() => begin(props)} // using props here
>
start
</button>
</div>
);
};
Simple, right ?

Passing Props between components

I am creating a bit of a playground to learn react and I've hit a road block with passing props between components. I essentially have two components, 1 that is the base component and then another that renders it out on the page with some extras (which i've removed for simplicity sake). I essentially want to be able to reuse the items in other places.
I'd like to be able to, when rendering the component in the example specify if it is type=submit if nothing specified default to type=button.
I'm clearly missing the point here because I get the error Cannot read property 'props' of undefined with the below code. Any help would be appreciated
Button Component
import React, {PropTypes} from 'react';
import './button_component.scss';
const propTypes = {
type: PropTypes.string
}
const ButtonComponent = () => {
return <button type={this.props.type}>button</button>
}
ButtonComponent.propTypes = propTypes;
export default ButtonComponent;
Then I have a component that outputs my item
import React from 'react';
import ButtonComponent from './button_component';
import Example from './example'
export default () =>
<Example>
<ButtonComponent type='button' />
</Example>;
ButtonComponent is a functional component. Hence, you can not use this.props in its code.
You should introduce props argument
const ButtonComponent = (props) => {
return <button type={props.type}>button</button>
}
Object destructuring and defaultProps can help you make your code simpler
const ButtonComponent = ({ type }) => {
return <button type={type}>button</button>
}
ButtonComponent.defaultProps = {
type: 'button'
}
then you can simply put <ButtonComponent /> to render a button.

Resources