cannot read of props null in react js - reactjs

when trying to click the delete button the error is displayed stating that cannot read props of null and try to bind the method in the constructor class using bind.this but again the same error is displayed. also bind the value at the bottom of the component again the same error that cannot read value of props as null
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import SampleData from './data.js';
import _ from 'lodash';
import AppList from './Applist';
import Appointment from './Appointment';
import './App.css';
class App extends Component {
constructor(){
super()
this.state = {
data:[],
aptBodyVisible: false
}
this.deleteMessage = this.deleteMessage.bind(this);
this.toggleAddDisplay = this.toggleAddDisplay.bind(this);
}
componentDidMount(){
this.setState({data: SampleData})
}
deleteMessage(item) {
var allApts = this.state.data;
var newApts = _.without(allApts, item);
this.setState({
data: newApts
});
}
toggleAddDisplay(){
var tempVisibility = !this.state.aptBodyVisible;
this.setState({
aptBodyVisible: tempVisibility
})
}
render() {
var filtered = this.state.data;
filtered = filtered.map((item, index)=>{
return(
<AppList key = { index }
singleItem = { item }
whichItem = { item }
onDelete = {this.deleteMessage}
/>
)
})
return (
<div className="main">
<Appointment
bodyVisible = { this.state.aptBodyVisible }
handleToggle = { this.toggleAddDisplay } />
<ul className="item-list media-list">{filtered} </ul>
</div>
);
}
}
export default App;
child class component
import React, { Component } from 'react';
class AppList extends Component {
handleDelete(){
this.props.onDelete(this.props.whichItem);
}
render(){
return(
<li className="pet-item media">
<div className="media-left">
<button className="pet-delete btn btn-xs btn-danger"
onClick = {this.handleDelete}>
<span className="glyphicon glyphicon-remove"></span></button>
</div>
<div className="pet-head">
<span className="pet-name">{this.props.singleItem.petName}</span>
<span className="apt-date pull-right">{this.props.singleItem.aptDate}</span>
</div>
<div className="owner-name"><span className="label-item">Owner:</span>
{this.props.singleItem.ownerName}</div>
<div className="apt-notes">{this.props.singleItem.aptNotes}</div>
</li>
)
}
}
export default AppList;

From the React Documentation
The constructor for a React component is called before it is mounted. When implementing the constructor for a React.Component subclass, you should call super(props) before any other statement. Otherwise, this.props will be undefined in the constructor, which can lead to bugs.
Like this:
constructor(props){
super(props);
this.state = {
data:[],
aptBodyVisible: false
}
this.deleteMessage = this.deleteMessage.bind(this);
this.toggleAddDisplay = this.toggleAddDisplay.bind(this);
}

yes again we need to bind the method in the child components even to work with the click events
onClick = {this.handleDelete.bind(this)}

Related

TypeError: this.props.changeUser is not a function

I am new in React Js and want to call the parent method from the child method.
There is a class login.jsx when someone clicks on submits button then a method changeUser in FirstPage.jsx should be invoked but when I try the online solution I am getting same error again and again that this.props.changeUser is not a function.
Login.jsx (child class)
import React, { Component } from 'react';
class Login extends Component {
constructor(props){
super(props);
this.state ={
user : null
}
this.onNameChange = this.onNameChange.bind(this);
this.onHandleClick = this.onHandleClick.bind(this);
}
onNameChange = (event)=>{
this.setState({
user:event.target.value
})
}
onHandleClick=(event)=>{
event.preventDefault();
this.props.changeUser("hello");
}
render() {
return (
<form>
<h3>Sign In</h3>
<div>
<label>User Name</label>
<input type="text" name="userId" placeholder="Enter User name" onChange ={this.onNameChange}/>
</div>
<button className="btn btn-primary btn-block" onClick={this.onHandleClick}>Submit</button>
</form>
);
}
}
export default Login;
FirstPage.jsx (parent class)
import React, { Component } from 'react';
import Login from './Login';
class Firstpage extends Component {
constructor(props){
super(props);
this.state=
{
user:null
}
this.changeUser = this.changeUser.bind(this)
}
changeUser =(x)=>{
console.log(x)
}
render() {
return (
<div>
<Login changeUser ={this.changeUser}/>
</div>
);
}
}
export default Firstpage;import React, { Component } from 'react';
import Login from './Login';
class Firstpage extends Component {
constructor(props){
super(props);
this.state=
{
user:null
}
this.changeUser = this.changeUser.bind(this)
}
changeUser =(x)=>{
console.log(x)
}
render() {
return (
<div>
<Login changeUser ={this.changeUser}/>
</div>
);
}
}
export default Firstpage;
I am getting an error that TypeError: this.props.changeUser is not a function
Please help me.
try to avoid using a lambda expression within you class component. Just create a simple member function:
import React, { Component } from 'react';
import Login from './Login';
class Firstpage extends Component {
constructor(props){
super(props);
this.state=
{
user:null
}
this.changeUser = this.changeUser.bind(this)
}
changeUser(x) // Try to declare this as member function
{
console.log(x)
}
render() {
return (
<div>
<Login changeUser ={this.changeUser}/>
</div>
);
}
}
export default Firstpage
You are making a mistake here while binding , inside constructor
//WRONG
this.onNameChange = this.onNameChange.bind(this);
this.onHandleClick = this.onHandleClick.bind(this);
//RIGHT
this.onNameChange = onNameChange.bind(this);
this.onHandleClick = onHandleClick.bind(this);
CODE:
constructor(props){
super(props);
this.state ={
user : null
}
this.onNameChange = onNameChange.bind(this);
this.onHandleClick = onHandleClick.bind(this);
}

onMouseOver is not working? but its working as onClick in react

onmouse is not working when I hover my mouse on the text in h1 tag, but its printing value in the console when I click on it.
import React, {
Component
} from 'react';
class App extends Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick = (event) => {
let word = event.target.innerText;
console.log(word)
}
render() {
return (<div>
<div className="App">
<h1 onMouseOver = {this.handleClick}>hover Me</h1>
</div>
</div>);
}
}
export default App;
the code works fine, only the "super(props)" part has been deprecated, another trick: when you use Arrow functions you don't need to bind the function in the constructor. This is the complete code:
import React, { Component } from 'react';
class YourComponent extends Component {
constructor(props) {
super();
this.state={};
}
handleClick = (event) => {
let word = event.target.innerText;
console.log(word)
}
render() {
return (
<div>
<div className="App">
<h1 onMouseOver={this.handleClick}> hover Me </h1>
</div>
</div>
);
}
}
export default YourComponent;
Enjoy ;)

React - Cannot render list item that is retrieved from API

I am writing a react application that outputs a list of books (image, title, category, and description).
My search bar and booklist are sibling components and the search bar will pass data to the booklist.
when clicking the search button, only "Sample Category" shows up but not anything else. There is no problem accessing the API and the data is not null.
Here is a sample API output: https://www.googleapis.com/books/v1/volumes?q=lordoftherings
My code is the following:
// App
import React, { Component } from 'react';
import Axios from 'axios';
import './App.css';
import SearchBar from './SearchBar';
import BookList from './BookList';
class App extends Component {
constructor(props) {
super(props);
this.state = {
books: []
};
this.search = this.search.bind(this);
}
search(title) {
const promise = Axios.get('https://www.googleapis.com/books/v1/volumes?q=' + title);
promise.then((response) => {
const books = response.data.items;
this.setState({ books: books });
console.log(this.state.books);
})
};
render() {
return (
<div className="App">
<SearchBar searchBooks = {this.search}/>
<BookList booklist = {this.state.books}/>
</div>
);
}
}
export default App;
// Search Bar
import React, { Component } from 'react';
import PropTypes from 'prop-types';
class SearchBar extends Component {
constructor(props) {
super(props);
this.state = { titleToSearch: 'harry potter' }
this.handleInputChange = this.handleInputChange.bind(this);
}
handleInputChange(e) {
this.setState({ titleToSearch: e.target.value });
};
render() {
return (
<form>
<input
type="text"
name="booksInput"
placeholder="Enter book title"
value={this.state.titleToSearch}
onChange={this.handleInputChange}
/>
<button type="button" onClick={() => this.props.searchBooks(this.state.titleToSearch)}>Search</button>
</form>
);
}
}
export default SearchBar;
// BookList
import React, { Component } from 'react';
class BookList extends Component {
render() {
const books = this.props.booklist;
return (
<div className="table">
{books.map((book) => {
console.log(book.id);
return (
<div className="box" key={book.id}>
<div className="img"><img src="assets/default-placeholder.jpg" alt="" /></div>
<div className="title">{book.title}</div>
<div className="category">Sample Category</div>
<div className="description">{book.description}</div>
</div>
);
})}
</div>
);
}
}
export default BookList;
In the sample code you provided, you're not actually dynamically outputting categories.
You've hard coded 'Sample category' in there.
book.category
...is not actually in the dataset.
There are categories which seem to be available under:
<div className="category">{book.volumeInfo.categories[0]}</div>
although you'll want to check if the array has length, and probably map or join each item in array to string.
just to be clear: the issue with your other fields is also that they're children of "volumeInfo"

Passing method child's component to another 'external' component in ReactJS

I'm new to ReactJs, coding and this is my first time posting here! So, I'm trying to build a Todo app in ReactJs. I have four components.
the first compo. is App.js - the parent one
import React, { Component } from 'react';
import TaskTodo from './TaskTodo';
import './App.css';
import TaskDisplayed from "./TaskDisplayed";
class App extends Component {
render() {
return (
<div className="App">
<header className="App-header">
<h1 className="App-title">Hey, i'm the header! </h1>
</header>
<div className="App-intro">
<TaskTodo/>
</div>
<div className="App-right">
<TaskDisplayed/>
</div>
</div>
);
}
}
export default App;
TaskTodo.js - which is the parent of the TodoItems.js
import React, {Component} from 'react';
import TodoItems from './TodoItems';
export default class TaskTodo extends Component{
constructor(props) {
super(props);
this.state = {
items: []
};
this.addItem = this.addItem.bind(this);
};
addItem(e) {
const itemArray = this.state.items;
if (this._inputElement.value !== "") {
itemArray.unshift(
{
text: this._inputElement.value,
key: Date.now()
}
);
this.setState({
items: itemArray
});
this._inputElement.value = "";
}
e.preventDefault();
}
render() {
return (
<div className="todoListMain">
<div className="header">
<form onSubmit={this.addItem}>
<input type="text" ref={(a) => this._inputElement = a}
placeholder="Add a list">
</input>
</form>
</div>
<TodoItems entries={this.state.items}/>
</div>
);
}
}
TodoItems.js - the child of the TaskTodo.js
import React, { Component } from 'react';
class TodoItems extends Component {
constructor(props) {
super(props);
this.createTasks = this.createTasks.bind(this);
}
handleClick = (text) => {
console.log(text);
}
createTasks(item) {
return <li key={item.key}><a onClick={() => this.handleClick(item.key, item.text)} href={'#about'}>#{item.text}</a></li>
}
render() {
const todoEntries = this.props.entries;
const listItems = todoEntries.map(this.createTasks);
return (
<ul className="theList">
{listItems}
</ul>
);
}
};
export default TodoItems;
What I need to do, is how I can pass the handleClick method (a child's of TaskTodo) to an 'external' component - TaskDisplayed.js; or how I can track when the user click to a listed item? Please pardon me for this unprofessional way of asking! But, I truly need to get in track with ReactJS! Thanks!
p.s. The above code I found online, so thanks for that :D!
You should define the onClick event handler in the parent component and pass it to the child as a prop.
See How to pass an event handler to a child component in React
In this case, you would want to define it in the App component since that is the parent of the two components that need to communicate.

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