I'm new to react and I'm getting an error for the state and method:
./src/App.js
Line 5: 'state' is not defined no-undef
Line 8: 'inputchangehandler' is not defined no-undef
This is my code until now:
import React from 'react';
import './App.css';
function App() {
state = {
userInput: ''
}
inputchangehandler = (event) => {
this.setState = ({
userInput: event.target.value
})
}
return (
<div className="App">
<input type="text" name="name"
onChange={this.inputchangehandler}
value = {this.state.userInput}/>
</div>
);
}
export default App;
In react there are 2 types of components.
Functional Components(like you used)
Class Components
Functional Components are stateless(in older versions, you can use hooks now) components. So if you want to directly use state you should change your components to class based component like this:
import React, { Component} from 'react';
import './App.css';
class App extends Component {
state = {
userInput: ''
}
inputchangehandler = (event) => {
this.setState = ({
userInput: event.target.value
})
}
render(){
return (
<div className="App">
<input type="text" name="name"
onChange={this.inputchangehandler}
value = {this.state.userInput}/>
</div>
);
}
}
export default App;
Functional component don't have state, form React 16.8 we have Hooks.
You should use useState hook for state.
import React, {useState} from 'react';
const [userInput, setUserInput] = useState('')
Usage,
<input type="text" name="name"
onChange={inputchangehandler}
value = {userInput}/>
inputchangehandler function should be,
const inputchangehandler = (event) => {
setUserInput(event.target.value)
}
Demo
Note: Functional component don't have access to this.
You have created functional component which does not have state. Define App as class component like below :
import React, { Component } from 'react';
import './App.css';
class App extends Component {
constructor(props) {
super(props);
this.state = {
userInput: ''
}
}
inputchangehandler = (event) => {
this.setState = ({
userInput: event.target.value
})
}
render() {
return (
<div className="App">
<input type="text" name="name"
onChange={this.inputchangehandler}
value={this.state.userInput} />
</div>
);
}
}
export default App;
You need to define state in your class's constructor like below:
constructor(props) {
super(props);
this.state = {
userInput: ''
}
}
Declaring your component as a function you don't have state.
Try converting it in class component or in a function using Hooks according to react documentation.
If you are using React version greater than 16.8 then you can use the useState hook.
import React from 'react';
import './App.css';
function App() {
const [userInput, setUserInput] = useState(0);
inputchangehandler = (event) => {
setUserInput(event.target.value)
}
return (
<div className="App">
<input type="text" name="name"
onChange={this.inputchangehandler}
value = {userInput}/>
</div>
);
}
export default App;
Refer: https://reactjs.org/docs/hooks-state.html
If you are using an older version then you will need to convert it to a React.Component
If you don't want to write a class component, you should use hooks, so your code will be like this:
import React, { useState } from 'react';
import './App.css';
function App() {
const [userInput, setUserInput] = useState(undefined);
inputchangehandler = (event) => {
setUserInput(event.target.value)
}
return (
<div className="App">
<input type="text" name="name"
onChange={this.inputchangehandler}
value = {userInput}/>
</div>
);
}
export default App;
i was on React version 17 this worked for me for state undefined error:
Adding example from React official docs:
class Clock extends React.Component { constructor(props) {
super(props);
this.state = {date: new Date()}; }
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
); } }
Assuming you're working with a class component rather than a functional component (as mentioned in other answers), the error state is not defined can occur if you forgot to prefix it with this..
Instead of:
myFunction() {
let myVariable = state.myStateKey;
// ...
}
Do:
myFunction() {
let myVariable = this.state.myStateKey;
// ...
}
Related
2 components :- ClickCounter, mouseHoverCounter !
1 HOC component to do the counting work.
earlier I was counting the click and mouse hover by writing separate counter method in each component(cliccounter,mousehovecounter),
but
now, I'm trying to pass the component into hoc counter & get the new component with only one change , where I'm passing a props to originalComponent and returning it to see the behavior but its now working...
import React, { Component } from 'react'
import updatedComponent from './hocCounter'
class ClickCounter extends Component {
constructor(props) {
super(props)
this.state = {
counter:0
}
}
ClickCounterHandler = () =>{
this.setState((prevState)=>{
return {counter:prevState.counter+1}
})
}
render() {
const count=this.state.counter
return (
<div>
<button onClick={this.ClickCounterHandler}>{this.props.name} Clicked {count} Times</button>
</div>
)
}
}
export default updatedComponent(ClickCounter)
import React, { Component } from 'react'
import updatedComponent from './hocCounter'
class HoverMouseCounter extends Component {
constructor(props) {
super(props)
this.state = {
counter:0
}
}
MouseOverCounter(){
this.setState((prevState)=>{
return {counter:prevState.counter+1}
})
}
render() {
const count=this.state.counter
return (
<div>
<h1 onMouseOver={this.MouseOverCounter.bind(this)}>{this.props.name} Hovered For {count} Time(s)</h1>
</div>
)
}
}
export default updatedComponent(HoverMouseCounter)
import React from 'react'
const updatedComponent = originalComponent => {
class newComponent extends React.Component {
render(){
return <originalComponent name='Harsh'/>
}
}
return newComponent
}
export default updatedComponent
In App.js, I'm returning
<ClickCounter></ClickCounter>
<HoverMouseCounter></HoverMouseCounter>
this only !
Check the error in the console,
index.js:1 Warning: <originalComponent /> is using incorrect casing. Use PascalCase for React components, or lowercase for HTML elements. at originalComponent
This means You are using the small letter in originalComponent
React components are expected to start with a capital letter
Try this in you HOC component
import React from 'react'
const updatedComponent = OriginalComponent => {
class NewComponent extends React.Component {
render(){
return <OriginalComponent name='Harsh'/>
}
}
return NewComponent
}
export default updatedComponent
My code from App.js. The idea is that when you enter text in input the screen should be updated accordingly. For some reason set state isn't working and I don't know why.
import React, { Component } from 'react';
import UserOutput from './Components/UserOutput';
import UserInput from './Components/UserInput';
class App extends Component {
state = {
username: 'Adib',
};
changeUsername = (event) => {
this.setState({
username: event.target.value,
});
};
render() {
return (
<div className="App">
<UserInput changed={this.changeUsername} />
<UserOutput name={this.state.username} />
</div>
);
}
}
export default App;
My code from useroutput.js
import React from 'react';
const userOutput = (props) => {
return (
<div>
<p>Username: {props.name}</p>
<p>Hello {props.name}</p>
</div>
);
};
export default userOutput;
My code from userinput.js
import React from 'react';
const userInput = (props) => {
return <input type="text" onChanged={props.changed} />;
};
export default userInput;
You are using onChanged as the name of the event action on the input field in the userInput Component. replace it with
return <input type="text" onChange={props.changed} />;
Your UserInput component is using an onChanged event which is not a valid event in React, try using onChange instead.
import React from 'react';
const userInput = (props) => {
return <input type="text" onChange={props.changed} />;
};
export default userInput;
I have two component in my project one is Tag and the other is LandingTicker so i want when i click Tag componet update state for LandTicker componet, and landticker componet in different file.
how i can do that?
thank you.
Tag component code::
tag/index.js
import React from 'react';
import './index.scss';
class Tag extends React.Component {
handleClick(e) {
let tags = document.querySelectorAll('.show-clickable');
Array.from(tags).map(el => el.classList.remove('selected-tag'))
e.target.classList.add('selected-tag');
/*
Here i should update the state for LandingTicker component.
and remember any component in different file.
How i can do that???
*/
}
render() {
return (
<div
className="show-clickable"
onClick={this.handleClick}
>
click here
</div>
);
}
}
export default Tag;
LandingTicker component code::
LandingTicker/index.js
import React from 'react';
import TickerRow from './TickerRow';
import './index.scss';
class LandingTicker extends React.Component {
state = {
coin: 'USD'
}
render() {
return (
<div className="landing-ticker__body">
{selectCoin(this.state.coin)}
</div>
</div>
);
}
}
const selectCoin = (coin) => {
const coins = {
USD: ['BTCUSD', 'ETHUSD', 'EOSUSD', 'LTCUSD'],
EUR: ['BTCEUR', 'ETHEUR', 'EOSEUR'],
GBP: ['BTCGBP', 'EOSGBP'],
JPY: ['BTCJPY', 'ETHJPY'],
};
return (
coins[coin].map(el =>
<TickerRow symbol={el} key={el.toString()} />
)
);
}
export default LandingTicker;
Edit:
my component Hierarchy::
StatusTable
TagsTable
Tag
TickerSearch
LandingTickers
TickersRow
StatusTable component code::
import React from 'react';
import TagsTable from './TagsTable';
import TickerSearch from './TickerSearch';
import LandingTicker from './LandingTicker';
import './StatusTable.scss';
class StatusTable extends React.Component {
render() {
return (
<div className="status-table">
<TagsTable />
<TickerSearch />
<LandingTicker />
</div>
);
}
}
export default StatusTable;
React handle all its component data in the form of state and props(immutable). So it is easy to pass data from parent to child or one component to another using props :
Your Tag.js file:
import React, { Component } from "react";
import LandingTicker from "./LandTicker";
class Tag extends Component {
constructor(props) {
super(props);
this.state = {
trigger: true
};
}
handleClick(e) {
// do all logic here and set state here
this.setState({ trigger: this.state.trigger });
}
render() {
//And then pass this state here as a props
return (
<div className="show-clickable" onClick={this.handleClick}>
click here
<LandingTicker trigger={this.state.trigger} />
</div>
);
}
}
export default Tag;
Inside LandTicker.js file:
import React from 'react';
import TickerRow from './TickerRow';
import './index.scss';
class LandingTicker extends React.Component {
state = {
coin: 'USD'
}
render() {
//Catch your props from parent here
//i.e this.props(it contains all data you sent from parent)
return (
<div className="landing-ticker__body">
{selectCoin(this.state.coin)}
</div>
);
}
}
const selectCoin = (coin) => {
const coins = {
USD: ['BTCUSD', 'ETHUSD', 'EOSUSD', 'LTCUSD'],
EUR: ['BTCEUR', 'ETHEUR', 'EOSEUR'],
GBP: ['BTCGBP', 'EOSGBP'],
JPY: ['BTCJPY', 'ETHJPY'],
};
return (
coins[coin].map(el =>
<TickerRow symbol={el} key={el.toString()} />
)
);
}
export default LandingTicker;
I think this is the best answer for your question if you don't use state management system such as Redux or Mobx.
https://medium.com/#ruthmpardee/passing-data-between-react-components-103ad82ebd17
(you need to check third option)
I'm working on simple form element using react-js.
There are three component:
App
TakeInput
Index
problem is when user put text in input field setState() function not work properly and data not updated. For testing purpose when i'm placing console.log in app js component it shows undefined on console. anyone sort this please. I want to console the updated data when state update
App.js
import React, { Component } from 'react';
import InputField from './TakeInput';
class App extends Component {
state = {
userInp : '',
outText : ''
}
handlechanger2 = (v) => {
this.setState( () => ({
userInp: v,
}))
console.log(this.userInp);
}
render() {
return (
<div className="App">
<InputField changingVal={this.handlechanger2}/>
</div>
);
}
}
export default App;
TakeInput.JS
import React, { Component } from 'react';
class TakeInput extends Component{
state={
txt: ''
}
handlerChange = (e)=>{
const { changingVal } = this.props;
const v = document.getElementById("userInput").value;
changingVal(v);
// console.log(e.target.value);
this.setState({ txt: e.target.value })
}
render(){
return(
<input type="text" name="userInput" id="userInput" placeholder="Please Enter Text" onChange={this.handlerChange} value={this.txt}/>
)
}
}
export default TakeInput;
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(<App />, document.getElementById('root'));
serviceWorker.unregister();
it is about you are developing wrong way. I think you text input should be at your parent component
To read from state you should use this.state.abc
import React, { Component } from 'react';
class TakeInput extends Component{
handlerChange = (e)=>{
this.props.onChange(e.target.value);
}
render(){
return(
<input type="text" name="userInput" placeholder="Please Enter Text" onChange={this.handlerChange} value={this.props.txt}/>
)
}
}
export default TakeInput;
import React, { Component } from 'react';
import InputField from './TakeInput';
class App extends Component {
state = {
userInp : '',
outText : ''
}
handlechanger2 = (v) => {
this.setState( () => ({
userInp: v,
}))
console.log(this.state.userInp);
}
render() {
return (
<div className="App">
<InputField txt={this.state.userInp} onChange={this.handlechanger2}/>
</div>
);
}
}
export default App;
You're trying to console.log this.userInp. It should be this.state.userInp.
Also to see the update right after the last set state, you can do the following:
handlechanger2 = (v) => {
this.setState( () => ({
userInp: v,
}), function(){ console.log(this.state.userInp);}) // set a callback on the setState
}
I am building a react app that deals with budgeting and I have written the code for a BillContainer component and an AddBill component.
This is my code:
BillContainer.js
import React from 'react';
import BillList from './BillList';
import AddBill from './AddBill';
class BillContainer extends React.Component {
constructor(props) {
super(props)
this.state = {
bills: [
]
}
this.addBill = this.addBill.bind(this)
}
addBill(bill) {
this.setState((state) => ({
bills: state.bills.concat([bill])
}));
}
render() {
return (
<div>
<AddBill addNew={this.addBill} />
<BillList bills={this.state.bills} />
</div>
)
}
}
export default BillContainer;
and AddBill.js
import React from 'react';
class AddBill extends React.Component {
constructor(props) {
super(props)
this.state = {
newBill: ''
};
this.updateNewBill = this.updateNewBill.bind(this)
this.handleAddNew = this.handleAddNew.bind(this)
}
updateNewBill(e) {
this.setState({
newBill: e.target.value
})
}
handleAddNew(bill) {
this.props.addNew(this.state.newBill)
this.setState({
newBill: ''
})
}
render() {
return (
<div>
<input
type='text'
value={this.state.newBill}
onChange={this.updateNewBill}
/>
<button onClick={this.handleAddNew}> Add Bill </button>
</div>
)
}
}
export default AddBill;
and this is my AddBill.test.js test:
import React from 'react';
import ReactDOM from 'react-dom';
import Enzyme from 'enzyme';
import { shallow, mount, render } from 'enzyme';
import EnzymeAdapter from 'enzyme-adapter-react-16';
import AddBill from '../components/AddBill';
let Sinon = require('sinon')
Enzyme.configure({adapter: new EnzymeAdapter() });
it('Adds a bill to the list', () => {
const clickSpy = Sinon.spy(AddBill.prototype, 'handleAddNew');
const wrapper = shallow(
<AddBill />
);
wrapper.find('button').simulate('click');
expect(clickSpy.calledOnce).toEqual(true)
})
Im trying to test that a new bill gets added when the Add Bill button is clicked. I've passed the addBill function as a prop but the test is throwing the error TypeError: this.props.AddNew is not a function.
How do I prevent the error message and and make this.props.addNew() not undefined?
You can use jest.spyOn like so:
it('Adds a bill to the list', () => {
const wrapper = shallow(
<AddBill addNew={() => {}} />
);
const clickSpy = jest.spyOn(wrapper.instance(), 'handleAddNew');
wrapper.find('button').simulate('click');
expect(clickSpy).toHaveBeenCalledTimes(1);
})
You're not passing an addNew property:
const wrapper = shallow(
<AddBill addNew={yourAddNewFunction} />
);