react js variable can not shown in alert - reactjs

I'm learning react.js and dealing with the below code:
import React, { Component } from 'react';
class Counter extends Component {
state = {
counts:1,
tags:['tag1', 'tag2', 'tag3']
};
incrementIt() {
this.state.counts++;
console.log("counts value is ", this.state.counts);
}
btnClick(){
this.incrementIt = this.incrementIt.bind(this);
return (
<div>
<button onClick={this.incrementIt} className="btn btn-primary btn-sm">Click me</button>
</div>
)
}
render(){
return(
<div>
{this.btnClick()}
</div>
)
}
}
export default Counter;
I'm expecting counts shows in the alert window but not working, while it works when switch back to console.log(). How comes?

You want to clean up some of that code: use setState, don't directly manipulate state. Also, assign that state in your constructor; don't use bind; and remember that if you want to see state changes, you need to wait until the state actually updates (which you can do with a function as second argument to setState)
import React, { Component } from 'react';
class Counter extends Component {
constructor(props) {
super(props);
this.state = {
counts: 1
};
}
increment(evt) {
let curCount = this.state.count;
this.setState({ counts: curCount + 1}, () => {
console.log(`after incrementing, counts value is ${this.state.counts}.`);
});
}
render(){
return (
<div>
<button onClick={evt => this.increment(evt)} className="btn btn-primary btn-sm">Click me</button>
</div>
)
}
}
export default Counter;

Related

Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate

am trying to toggle the state of a component in ReactJS but I get an error stating:
Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.
I don't see the infinite loop in my code, can anyone help?
ReactJS component code:
import React from 'react'
import Buttonevent from './buttonevent.js'
class Button extends React.Component {
constructor (props) {
super(props);
this.state = {counter: 0};
}
clickHandler() {
this.setState({
counter: this.state.counter+1
}, function () {
console.log (" Job done");
});
}
render() {
return(
<div classname="app">
<div classname="click-count">
Button presses: {this.state.count}
</div>
<button onClick= {this.clickHandler.bind(this)}> Add one</button>
<Buttonevent></Buttonevent>
</div>
);
}
}
export default Button;
import React, { Component } from 'react';
class Buttonevent extends React.Component {
constructor() {
super();
this.state = { buttontext: "Click me Please"};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(() => {
return { buttontext: "Thanks, Button has been clicked !"}
});
}
render() {
const {buttontext} = this.state
return <button onClick ={this.handleClick()} > {buttontext} </button>
}
}
export default Buttonevent;
The below line of code is your problem
return <button onClick ={this.handleClick()} > {buttontext} </button>
The function is getting called because of this.handleClick() instead it should be like below
return <button onClick ={this.handleClick} > {buttontext} </button>

Change the state of parent component on click of a child component with a specific key in React JS

I am making a Todo App in React JS, i'm fairly new to React JS.
I have made two components named AddComponent and TodoItem component. The AddComponent has an input and button to add the todos and it will render TodoItem as a child component whenever a todo is added using the AddComponent.
I also have to remove the child component TodoItem when a button inside it is clicked according to it's key, so it would remove that item from the state of the parent component AddComponent.
The problem i'm facing is i can't change the state anywhere else than the render() function, because there is where i'm dynamically generating the TodoItem components using the state.
And changing the state inside the render() function would result in an infinite loop. Please help how to resolve this problem.
I'm using Bootstrap 4 using a CDN for styling.
AddComponent.js
import React from 'react'
import shortid from 'shortid'
import TodoItem from './TodoItem';
class AddComponent extends React.Component {
constructor() {
super();
this.state = {
todoText: '',
todoList: []
}
this.handleChange = this.handleChange.bind(this);
this.handleClick = this.handleClick.bind(this);
this.handleTodoClick = this.handleTodoClick.bind(this);
}
handleChange(e) {
e.persist();
this.setState((prevState) => {
return {
todoText: e.target.value,
todoList: prevState.todoList
}
})
}
handleClick() {
this.setState((prevState) => {
return {
todoText: prevState.todoText,
todoList: [{
text: prevState.todoText,
id: shortid.generate()
}, ...prevState.todoList]
}
})
}
handleTodoClick(id) {
const newState = this.state.todoList.filter(todoL => todoL.id === id);
this.setState({ todoList: newState });
}
render() {
const todos = this.state.todoList.map((todo) => {
return (
<TodoItem key={todo.id} value={todo.text} click={this.handleTodoClick(todo.id)}>{todo.text}</TodoItem>
)
})
return (
<div>
<div className="row">
<div className="col-sm-9">
<div className="form-group">
<input
type="text"
className="form-control"
placeholder="Add a Todo"
onChange={this.handleChange}
/>
</div>
</div>
<div className="col-sm-3">
<button
type="button"
className="btn btn-primary btn-block"
onClick={this.handleClick}
>Add
</button>
</div>
</div>
<div>
{todos}
</div>
</div>
)
}
}
export default AddComponent
TodoItem.js
import React from 'react'
class TodoItem extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div className="alert alert-secondary alert-dismissible fade show">
<button
type="button"
className="close"
onClick={this.props.click}
data-dismiss="alert">×</button>
{this.props.value}
</div>
)
}
}
export default TodoItem
Try : https://codesandbox.io/s/hopeful-moon-duqfe
There were two problems; 1st one is filter and the 2nd one is handler callback function that is set to click prop.
1st problem : Filter function should filter that does not match your id so you should use NOT equal :
handleTodoClick(id) {
const newState = this.state.todoList.filter(todoL => todoL.id !== id);
this.setState({ todoList: newState });
}
2nd problem : When you set click prop as a handler callback function, you should set reference of the function itself without calling it. Not like this : click={this.handleTodoClick(todo.id). This will call the function and set the click prop to result of it, which is undefined since it does not return to anything.
So i have changed your click props as click={this.handleTodoClick}
const todos = this.state.todoList.map(todo => {
return (
<TodoItem key={todo.id} id={todo.id} value={todo.text} click={this.handleTodoClick}>
{todo.text}
</TodoItem>
);
});
On child component, onClick is similary set to function itself onClick={() => this.props.click(this.props.id)} NOT like onClick={this.props.click(this.props.id)}.
import React from "react";
class TodoItem extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div className="alert alert-secondary alert-dismissible fade show">
<button
type="button"
className="close"
onClick={() => this.props.click(this.props.id)}
data-dismiss="alert"
>
×
</button>
{this.props.value}
</div>
);
}
}
Fix:
<TodoItem key={todo.id} todoId={todo.id} value={todo.text} click={this.handleTodoClick(todo.id)}>{todo.text}</TodoItem>
We can't use key as id. The key property is used by React under the hood, and is not exposed to us.
import React from 'react'
class TodoItem extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div className="alert alert-secondary alert-dismissible fade show">
<button
type="button"
className="close"
// look here
onClick={e => {this.props.click(this.props.todoId)}}
data-dismiss="alert">×</button>
{this.props.value}
</div>
)
}
}
export default TodoItem
Try the following by updating the handle for click in AddComponent then creating a handler within TodoItem that calls props click with the respective todo item id value. I'd recommend to just pass the entire todo so that you can access both the unique id and value in TodoItem:
AddComponent:
const todos = this.state.todoList.map((todo) => {
return (
<TodoItem key={todo.id} todo={todo} click={this.handleTodoClick}>{todo.text}</TodoItem>
)
})
TodoItem:
import React from 'react'
class TodoItem extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.props.click(this.props.todo.id);
}
render() {
return (
<div className="alert alert-secondary alert-dismissible fade show">
<button
type="button"
className="close"
onClick={this.handleClick}
data-dismiss="alert">×</button>
{this.props.todo.value}
</div>
)
}
}
export default TodoItem;

sending function throw `spread operator` not works but state value added

I am passing a function and a state value throw spread operator. the state value update in the html. but while click on button function not calling at all.
What is the correct way to send the function to children using spread operators in reactjs?
Here is my code :
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
class Counter extends React.Component {
render() {
return (
<div>
<div>{this.props.display}</div>
<button onClick={this.props.fun}>+</button> //onclick not works!!
</div>
);
}
}
class CounterParent extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0 //added
};
}
increase = () => { //not called
this.setState({
count: this.state.count + 1
});
};
render() {
let object = {
display: this.state.count,
func: this.increase
};
return (
<div >
<Counter {...object} />
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<CounterParent />, rootElement);
In Counter component, you mispelled func name.
class Counter extends React.Component {
render() {
return (
<div>
<div>{this.props.display}</div>
<button onClick={this.props.func}>+</button>
</div>
);
}
}

React component not recognizing .filter as a function

So I am making a react app for food recipes and am pulling data from a JSON file. For some reason the .filter and .map of the recipes is not showing as a function. Any help greatly appreciated.
It most examples it looks like you can add this info under render. I am a noob with both coding and react so I am sure it is user error.
import React from 'react';
import ReadInput from'./readInput';
import '../Styles/Home.css';
class Input extends React.Component{
constructor(props) {
super(props);
this.state = {
value:''
}
this.handleName = this.handleName.bind(this);
};
handleName(e){
console.log('handleName')
if(e === 'chicken'){
this.setState({value: 1})
} else if (e === 'beef') {
this.setState({value: 2})
} else if (e === 'rice'){
this.setState({value: 3})
}
}
render(){
const menu = this.props.data.filter((recipe) => {
if(recipe.id === this.state.value){
return recipe.dish;
}
})
.map(recipe => {
return(
<div>
<li key={recipe.id}>{recipe.dish}</li>
<li >{recipe.ingredients}</li>
</div>
)
})
return(
<div>
<ReadInput
onChange={this.handleName} />
<button className="homeButton" onClick={this.menu}>Click</button>
<ul className='listStyle'>
{menu}
</ul>
</div>
)
}
}
export default Input;
app file
import React from 'react';
import Input from'./Input';
import recipes from'../data.json';
class App extends React.Component{
constructor(props) {
super();
}
render(){
return(
<div>
<Input data={recipes} />
</div>
)
}
}
export default App;
Use timeout function or check your response, it may come later, before that your function may running. use timeout and check it.
if (timerid) {
clearTimeout(timerid);
}
timerid = setTimeout(() => {
this.reqMaq(obj['fkmaqid'])
}, 2000);
If this.props.data is an object, you cannot directly map or filter on it. I think this should work:
const recipes = this.props.data;
const menu = Object.keys(recipes).filter((recipeKey) => recipes[recipeKey].id === this.state.value)
.map(recipeKey =>
return (
<div key={recipes[recipeKey].id}>
<li>{recipes[recipeKey].dish}</li>
<li>{recipes[recipeKey].ingredients}</li>
</div>
);
});
First you filter the keys of your this.props.data, you only get the keys for the recipes that match the id in the state.
Then you map (still mapping with the keys of the object, not the values) and create the list.
Notice that I moved the key attribute to the <div> tag, that's because you need this attribute in the component returned by the map, not in it's children.
Also, in the <button className="homeButton" onClick={this.menu}>Click</button>, the onClick attribute receives the menu, but it should receive a function to execute when the button is clicked.

State is undefined in scope of map

I am new to reactjs and trying to learn the concepts. I am creating demo sticky notes app on reactjs. I am getting error
index.js: Uncaught TypeError: Cannot read property 'notes' of undefined
I have Board component and Notes components as follows.
Notes Component:
import React from 'react';
import ReactDOM from 'react-dom';
class Note extends React.Component {
constructor() {
super();
this.state = {editing: false}
this.edit = this.edit.bind(this);
this.save = this.save.bind(this);
}
edit() {
this.setState({editing: true});
}
save() {
this.props.onChange(ReactDOM.findDOMNode(this).value, this.props.index);
this.setState({editing: false});
}
remove() {
this.props.onRemove(this.props.index);
}
renderDisplay() {
return (
<div className='note'>
<p>{this.props.children}</p>
<span>
<button onClick={this.edit} className='btn btn-primary glyphicon glyphicon-pencil'/>
<button onClick={this.remove} className='btn btn-danger glyphicon glyphicon-trash'/>
</span>
</div>
);
}
renderForm() {
return (
<div className='note'>
<textarea className='form-control' defaultValue={this.props.children} ref='newText'></textarea>
<button className='btn btn-success btn-sm glyphicon glyphicon-floppy-disk' onClick={this.save} />
</div>
);
}
render() {
if(this.state.editing) {
return this.renderForm();
} else {
return this.renderDisplay();
}
}
}
export default Note;
And Board Component:
import React from 'react';
import ReactDOM from 'react-dom';
import Note from './Note';
class Board extends React.Component {
constructor(props) {
super(props);
this.state = {
notes: [
'Check emails',
'Log in to jira',
'Fix the issues',
'Logout the system'
]
}
}
update(newText, i) {
console.log(this);
console.log(this.state);
var arr = this.state.notes;
arr[i] = newText;
this.setState({notes: arr});
}
remove(i) {
var arr = this.state.notes;
arr.splice(i, 1);
this.setState({notes: arr});
}
eachNote(note, i) {
return (
<Note key={i}
index={i}
onChange={this.update}
onRemove={this.remove}
>{note}</Note>
);
}
render() {
return (
<div className='board'>
{this.state.notes.map(this.eachNote, this)}
</div>
);
}
}
ReactDOM.render(<Board></Board>, document.getElementById('react-container'));
export default Board;
I am getting error when i try to update a note, as the note is render using the state notes variable and i have attached a property on each note as onChange: {this.update}. In update i am accessing state variable notes but state is undefined.
Can anyone give me suggestions about it. Thanks
Try:
onChange={this.update.bind(this)}
Instead of:
onChange={this.update}
For better performance, React recommends binding event handlers in the constructor so they are only bound once for every instance.
Read more here: https://facebook.github.io/react/docs/reusable-components.html#no-autobinding

Resources