'delTodo' is not defined. React (line 51) - reactjs

Error:
'delTodo' is not defined. React (line 51)
I am new to React. Here is the code; what did I do wrong?
import React, { Component } from 'react';
import Todos from './components/Todos';
import markComplete from './components/Todos'
import './App.css';
class App extends Component {
constructor(props) {
super(props);
this.state = {
todos: [
{
key: 1,
title: 'Take out the trash',
completed:false
},
{`enter code here`
key: 2,
title: 'Dinner with wife',
completed:true`enter code here`
},
{
key: 3,
title: 'Meeting with boss',
completed:false
}
]
}
}
asd = () =>{
}
// Toggle Complete
markComplete = (key) => {
this.setState({ todos: this.state.todos.map(todo=> {
if(todo.key === key) {
todo.completed = !todo.completed
}
return todo;
}) });
}
//Delete Todo
delTodo = (key) => {
console.log(key)
}
render() {
return (
<div className="App">
<Todos todos={this.state.todos} markComplete={markComplete}
delTodo={delTodo} />
</div>
);
}
}
export default App;

If you're using a class component, you need to use the this keyword when you refer to class attributes (state, methods, etc.). So the method should be this.delTodo:
return (
<div className="App">
<Todos
todos={this.state.todos}
markComplete={this.markComplete}
delTodo={this.delTodo}
/>
</div>
)

Related

My checkbox is not changing from check or uncheck, but I can see that state value is changing, what's going on?

So when I run this and check the checkbox, I can see the values changing in the state, but why is the checkbox control not changing its status from check/uncheck? I know the render() method is being hit as well. Why, oh why, Gods of code? Lost in hours of figuring out what's wrong and I'm lost!
bob-Todos.js FILE
class Todo extends React.Component {
constructor(param) {
super();
this.state = {
id: param.data.id,
text: param.data.text,
completed: param.data.completed,
onMyChange: param.OnChange,
};
}
render() {
console.log("In TODO Render");
return (
<div>
<p>
<input
type="checkbox"
onChange={() => {
this.state.onMyChange(this.state.id);
}}
checked={this.state.completed}
/>
{this.state.text}
</p>
</div>
);
}
}
export default Todo;
Bob-App.js FILE
import React, { Component } from "react";
import Todo from "./bob-Todo";
import todoData from "../data/bob-todosData";
class App extends Component {
constructor() {
super();
this.state = { data: todoData };
this.OnChange = this.OnChange.bind(this);
}
OnChange(myId) {
this.setState((prev) => {
let updatedTodos = prev.data.map((todo) => {
if (todo.id === myId) {
todo.completed = !todo.completed;
}
return todo;
});
return { data: updatedTodos };
});
console.log(this.state.data);
}
render() {
return this.state.data.map((item) => {
return <Todo key={item.id} data={item} OnChange={this.OnChange} />;
});
}
}
export default App;
bob-todosData.js FILE
const todosData = [
{
id: 1,
text: "take out the trash",
completed: true
},
{
id: 2,
text: "rest for a while and relax",
completed: false
},
{
id: 3,
text: "watch an online movie",
completed: true
}
]
export default todosData
index.js FILE
import React from 'react';
import ReactDOM from 'react-dom';
import AppBob from "./bobComponents/Bob-App";
ReactDOM.render(
<AppBob />, document.getElementById('root')
);
You don't need to assign your props to state in your Todo component
Just remove them and invoke the function also use those variables directly:
Then your component will be:
class Todo extends React.Component {
render() {
const {
data: {
id,
text,
completed,
},
OnChange, // <-- Should rename this to "onChange"
} = this.props;
console.log('In TODO Render');
return (
<div>
<p>
<input
type="checkbox"
onChange={() => {
OnChange(id);
}}
checked={completed}
/>
{text}
</p>
</div>
);
}
}
export default Todo;
Also, rename your OnChange function to onChange to enable js convention

Error: Super expression must either be null or a function

Problem
So as the title said i've this issue in a todoapp. i checked if i had some typo like react instead of React and it seems to be alright.
Before post something i checked:
First post stackoverflow
Second post stackoverflow
but i cannot find a solution
Code
App.js
import React, {Component} from 'react';
import Form from './Components/Form';
import Footer from './Components/Footer';
import Header from './Components/Header';
class App extends React{
constructor(props) {
this.state = {
todoValue: "",
filterType: "All",
todos: [],
}
}
handleChange = (event) => {
this.setState({
todoValue: event.target.value,
})
}
handleClick = (event) => {
event.preventDefault();
if (this.state.todoValue !== "") {
const todo = {
id: Date.now(),
text: this.state.todoValue,
done: false,
}
this.setState({
todoValue: "",
todos: [todo, ...this.state.todos],
})
}
}
handleToggle = (id) => {
this.setState((prevState) => {
return {
todos: prevState.todos.map((item, i) => {
if (item.id === id) {
return {
...item,
done: !prevState.todos[i].done,
}
}
return item;
})
}
})
}
handleDelete = (id) => {
this.setState({
todos: this.state.todos.filter(item => item.id !== id)
})
}
deleteCompleted = () => {
this.setState({
todos: this.state.todos.filter(item => !item.done)
})
}
getVisibleTodos = () => {
const filterType = this.state.filterType;
let filterState = null;
switch (filterType) {
case "Completed":
return filterState = this.state.todos.filter(item => item.done);
case "Active":
return filterState = this.state.todos.filter(item => !item.done);
case "Originals":
return filterState = this.state.todos.filter(item => !item.done);
case "New":
return filterState = this.state.todos.filter(item => !item.done);
default:
return filterState = this.state.todos;
}
}
setActiveFilter = (text) => {
this.setState({
filterType: text,
})
}
render() {
return (
<div className="container">
<Header countTodo={this.state.todos.length}/>
<Form handleDelete={this.handleDelete}
handleToggle={this.handleToggle}
handleClick={this.handleClick}
handleChange={this.handleChange}
todoValue={this.state.todoValue}
todos={this.getVisibleTodos()}/>
<Footer setActiveFilter={this.setActiveFilter}
deleteCompleted={this.deleteCompleted}
filter={this.state.filterType}/>
</div>
)
}
}
export default App;
Header.js
import React from 'react';
class Header extends React.Component {
render() {
return (
<header className="header">
<h3>All To-Do {this.props.countTodo}</h3>
</header>
)
}
}
export default Header;
Form.js
import React, {Component} from'react';
import Todo from './Todo';
class Form extends React {
render() {
return (
<form className="form">
<input type="text"
className="form__input"
placeholder="Items"
onChange={this.props.handleChange}
value={this.props.todoValue}
/>
<button
className="form__button"
type="submit"
onClick={this.props.handleClick}>╋</button>
<Todo
todos={this.props.todos}
handleToggle={this.props.handleToggle}
handleDelete={this.props.handleDelete}
/>
</form>
)
}
}
export default Form;
and the last modul is Todo.js
import React, {Component} from 'react';
class Todo extends React{
render() {
return (
<ul className="todos-list">
{
this.props.todos.map((item) => {
return (
<li className="todo-item"
key={item.id} onClick={() => this.props.handleToggle(item.id)}>
<span
className={item.done ? "todo-item__name disabled" : "todo-item__name"}>
{item.text}
</span>
<span
className="todo-item__delete-button"
onClick={() => this.props.handleDelete(item.id)}>
×
</span>
</li>
)
})
}
</ul>
)
}
}
export default Todo;
You class should extend from Component that you're importing from react library.
It should be either
class App extends Component{}
or if you didn't import Component then
class App extends React.Component{}
You haven't extended your App component correctly
class App extends React{ // error here
constructor(props) {
this.state = {
todoValue: "",
filterType: "All",
todos: [],
}
}
Extend it from React.Component
class App extends React.Component {
constructor(props) {
super(props); // use super here
this.state = {
todoValue: "",
filterType: "All",
todos: [],
}
}

How to add props to state

I have a problem when trying to add my redux array to a component’s state:
componentDidMount() {
this.props.cardAction()
this.setState({ showCards: this.props.cardAction() })
}
hhhhhh undefined console log undefined
Here’s my dashboard code:
import React, { Component } from 'react'
import { connect } from 'react-redux'
import PropTypes from 'prop-types'
import Header from '../../common/Header/'
import Masonry from '../../common/Masonry/'
import { cardAction } from '../../store/actions/Cards'
import Arrow_Down from '../../assets/img/arrow-down.svg'
class Dashboard extends Component {
componentDidMount() {
this.props.cardAction()
this.setState({ showCards: this.props.cardAction() })
}
constructor(props) {
super(props)
this.state = {
collapsed: true,
class: 'collapsed',
showCards: {},
}
this.toggleCollapse = this.toggleCollapse.bind(this);
}
toggleCollapse(i, info) {
console.log('i', info, 'iiiii', i)
this.setState({
collapsed: !this.state.collapsed,
class: this.state.collapsed ? '' : 'collapsed',
showCards: info
}, () => {
// my state is updated here !
console.log('cardsss', this.state.showCards)
})
if (this.state.showCards === 'active') {
let carddd = this.state.showCards
this.setState({
showCards: {
...this.state.showCards,
open: 'inactive'
}
});
}
else {
this.setState({
showCards: {
...this.state.showCards,
open: 'active'
}
});
}
}
render() {
console.log('hhhhhh', this.state.showCards)
const cardList = this.props.Cards.map((info, i) => {
return (
<div className={(info.open === 'active') ? 'collapsed' : ''} key={i}>
<div className={(info.open === 'active') ? 'header flex space-between active' : 'header flex space-between'}>
<h2>{info.title}</h2>
<span onClick={() => { this.toggleCollapse(i, info) }}><img src={Arrow_Down} alt='Arrow' /></span>
</div>
<div className='content'>
<p>{info.description}</p>
</div>
</div>
)
})
return (
<div>
<Header />
<Masonry columns={3} gap={20}>
{cardList}
</Masonry>
</div>
)
}
}
Dashboard.defaultProps = {
columns: 2,
gap: 20,
Cards: []
}
Dashboard.propTypes = {
Cards: PropTypes.array.isRequired,
}
const mapStateToProps = state => {
return { Cards: state.cards.result }
}
const mapDispatchToProps = dispatch => ({
cardAction: () => dispatch(cardAction())
})
export default connect(mapStateToProps, mapDispatchToProps)(Dashboard)
this.props.cardAction() is a redux action, it's not meant for you to directly assign to state, reason is redux action will return to reducer, not component. You should remove the setState in componentDidMount
componentDidMount() {
this.props.cardAction();
}
When you invoked this.props.cardAction(), it will call the function that defined in redux action file, and the result will be available at this.props.Cards as you mentioned above
const mapStateToProps = state => {
return { Cards: state.cards.result }
}

React setState called multiple times on the same state object

I have the following:
import React from 'react';
import ReactDOM from 'react-dom'
import {render} from 'react-dom';
import Forms from './forms/forms.jsx';
class Option1 extends React.Component {
render () {
return (
<p>Icon 1</p>
)
}
}
class TShirt extends React.Component {
render () {
console.log(this.props.currentState);
return <div className="thsirt">
<h1>{this.props.name}</h1>
<p>{this.props.iconID}</p>
{this.props.optionA ? <Option1 /> : ''}
</div>;
}
}
class Link extends React.Component {
render () {
return (
<li
data-id={this.props.el}
onClick={this.props.onClick}
className={this.props.activeClass}>{this.props.el}
</li>
);
}
}
class Nav extends React.Component {
getComponentID (id) {
switch(id) {
case 'name':
return 1;
break;
case 'color':
return 2;
break;
case 'design':
return 3;
break;
case 'share':
return 4;
break;
}
}
handleClick (event) {
// setting active class
var id = event.target.getAttribute("data-id");
this.props.action(id);
// switching coomponent based on active class
var component = this.getComponentID(id);
this.props.switchComponent(component);
}
render () {
var links = ['name', 'color', 'design', 'share'],
newLinks = [],
that = this;
links.forEach(function(el){
newLinks.push(<Link
onClick={that.handleClick.bind(that)}
activeClass={that.props.active == el ? 'active': ''}
key={el}
el={el}
/>
);
});
return (
<ol>
{newLinks}
</ol>
);
}
}
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
name: '',
color: '',
active: '',
formId: 1,
optionA: {
on: false,
icon_id: '',
option_id: '',
name: ''
}
};
this.setName = this.setName.bind(this);
this.setColor = this.setColor.bind(this);
this.setAtciveNavEl = this.setAtciveNavEl.bind(this);
this.setFormId = this.setFormId.bind(this);
this.setOptionA = this.setOptionA.bind(this);
this.setOptionAVisibility = this.setOptionAVisibility.bind(this);
}
setName (tshirt) {
this.setState({ name:tshirt })
}
setColor (color) {
this.setState({ color:color })
}
setAtciveNavEl (el) {
this.setState({ active:el })
}
setFormId (id) {
this.setState({ formId:id })
}
setOptionA (iconID, iconName) {
this.setState({
optionA:
{
icon_id: iconID,
name: iconName
}
})
}
setOptionAVisibility (onOff, optionID) {
this.setState({
optionA:
{
option_id: optionID,
on: onOff
}
})
}
render () {
return (
<section className={this.state.color}>
<Nav
active={this.state.active}
action={this.setAtciveNavEl}
switchComponent={this.setFormId}
/>
<TShirt
name={this.state.name}
icons={this.state.options}
optionA={this.state.optionA.on}
currentState={this.state}
/>
<Forms
name={this.state.name}
action={this.setName}
colorVal={this.setColor}
activeNav={this.setAtciveNavEl}
switchComponent={this.setFormId}
formID={this.state.formId}
setOptionA={this.setOptionA}
setOptionAVisibility={this.setOptionAVisibility}
/>
</section>
);
}
}
render(<App/>, document.getElementById('app'));
I need to populate this object at different times like this:
setOptionA (iconID, iconName) {
this.setState({
optionA:
{
icon_id: iconID,
name: iconName
}
})
}
setOptionAVisibility (onOff, optionID) {
this.setState({
optionA:
{
option_id: optionID,
on: onOff
}
})
}
The problem I have is taht when I console.log my state at:
class TShirt extends React.Component {
render () {
console.log(this.props.currentState);
return <div className="thsirt">
<h1>{this.props.name}</h1>
<p>{this.props.iconID}</p>
{this.props.optionA ? <Option1 /> : ''}
</div>;
}
}
after all my click events it seems like I loose the "on" and "option_id" from the optionA object.
Does calling setState on the same object override the previous setState?
If you are writing ES2015, you can use the spread operator to copy the whole object and just modify one of it's properties:
setOptionAVisibility (onOff, optionID) {
this.setState({
optionA:
{
...this.state.optionA,
option_id: optionID,
on: onOff
}
})
}
Can be very useful when modifying single properties of complex objects on the state tree.

Why is my react component not updating?

I have a simple Cart component and I want to show either a "Your cart is empty" message when there are no items in it.
import React, { Component } from 'react'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import * as CartActions from '../actions/cart'
import Shelf from './Shelf'
import EmptyCart from './EmptyCart'
/*
This is a container component
*/
class Cart extends Component {
constructor(props) {
super(props)
this.state = {
itemQuantity: props.cart.length
}
}
render() {
const CartItems = this.props.cart.map(
(item, idx) =><li key={idx}>{item.name} - ${item.price}</li>
)
const isCartEmpty = () => this.state.itemQuantity === 0
console.log("is cart empty? ", isCartEmpty(), "cart item quantity ", this.state.itemQuantity)
return(
<div className="Cart">
<Shelf addItem={this.props.action.addToCart} />
<h2>Cart Items</h2>
<ol>
{ isCartEmpty() ? <EmptyCart/> : {CartItems} }
</ol>
</div>
)
}
}
function mapStateToProps(state, prop) {
return {
cart: state.cart
}
}
function mapDispatchToProps(dispatch) {
return {
action: bindActionCreators(CartActions, dispatch)
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Cart)
My Shelf component looks like this:
import React, { Component } from 'react';
class Shelf extends Component {
constructor(props) {
super(props)
this.addItemToCart = this.addItemToCart.bind(this)
this.state = {
shelfItems: [
{ "name": 'shampoo', "price": 23 },
{ "name": 'chocolate', "price": 15 },
{ "name": 'yogurt', "price": 10 }
]
}
}
addItemToCart(item){
this.props.addItem(item)
}
render() {
const shelfItems = this.state.shelfItems.map((item, idx) => {
return <li key={idx}><button onClick={()=>this.addItemToCart(item)}>[+]</button>{item.name} - ${item.price}</li>
})
return(
<div>
<h2>Shelf</h2>
<ul>
{shelfItems}
</ul>
</div>
)
}
}
export default Shelf
Cart Reducer:
export default(state = [], payload) => {
switch (payload.type) {
case 'add':
return [...state, payload.item]
default:
return state
}
}
addToCart action:
export const addToCart = (item) => {
return {
type: 'add',
item
}
}
The empty message shows up but the list does not update when I add items. What am I doing wrong? The code works just fine if I remove the conditionals and just render CartItems
It's because you set only initial state. When you add item you don't set a new state. If you use redux there is no local state needed.
Try this:
class Cart extends Component {
constructor(props) {
super(props)
this.state = {}
}
render() {
const CartItems = this.props.cart.map(
(item, idx) =><li key={idx}>{item.name} - ${item.price}</li>
)
const isCartEmpty = CartItems.length === 0
return(
<div className="Cart">
<Shelf addItem={this.props.action.addToCart} />
<h2>Cart Items</h2>
<ol>
{isCartEmpty ? <li>Your Cart is Empty</li> : CartItems}
</ol>
</div>
)
}
}

Resources