So I'm new to react and Ive been playing around with it for the past few weeks. I keep on getting this "ERROR: this.props.addNew is not a function" error about the addNew function within the addTheFriend function and I dont know why? Everything seems to correct to me. Can anybody help me? Thank you in advance.
import React, { Component } from 'react';
import { render } from 'react-dom';
export default class HelloUser extends React.Component {
constructor(props) {
super(props);
this.state = { name: "TT", friendsCount: 0 , friends: ["SS", "JJ", "Ww"] };
this.addFriends=this.addFriends.bind(this);
this.componentWillMount=this.componentWillMount.bind(this);
}
addFriends(friend) {
this.setState({
friends: this.state.friends.concat([friend]),
friendsCount: this.state.friendsCount + 1
});
}
componentWillMount() {
this.setState({
friendsCount: this.state.friends.length
});
}
render() {
return (
<div>
Villain: {this.state.name}, No of friends: {this.state.friendsCount}<br />
<AddingTheFriend addNew={this.addFriends} />
<ListFriends enemies={this.state.friends} />
</div>
);
}
};
export default class ListFriends extends React.Component {
render() {
var allFriends = this.props.enemies.map(function (friend) {
return <li>{friend}</li>;
});
return (
<div>
Her evil friends:
<ul>{allFriends}</ul>
</div>
);
}
};
export default class AddingTheFriend extends React.Component {
constructor(props) {
super(props);
this.state= {newFriend: ''};
this.updateNewFriend = this.updateNewFriend.bind(this);
this.addTheFriend = this.addTheFriend.bind(this);
}
updateNewFriend(change) {
this.setState({
newFriend: change.target.value
});
}
addTheFriend() {
this.props.addNew(this.state.newFriend);
this.setState({
newFriend: ''
})
}
render() {
return (
<div>
<input type="text" value={this.state.newFriend} onChange={this.updateNewFriend} />
<button type="button" onClick={this.addTheFriend}>Add Friend</button>
</div>
)
}
};
render(<HelloUser />, document.getElementById('root'));
Related
I'm new to react and I've been playing around with it the past few days. I'm trying to append a value to the DOM, I found a way to do it but I'm looking for a way to do with by
var para = document.createElement("li");
var t = document.createTextNode(value);
para.appendChild(t);
document.getElementById("root").appendChild(para);
But, I'm looking for a different way. I tried a few different ways but I'm stuck. Is there a way other than this way above ^^^^
import React, { Component } from 'react';
import { render } from 'react-dom';
export class Parent extends React.Component {
constructor(props) {
this.greet = this.greet.bind(this);
this.state = { text: " " };
}
greet(value) {
//console.log(value);
var para = document.createElement("li");
var t = document.createTextNode(value);
para.appendChild(t);
document.getElementById("root").appendChild(para);
}
render() {
return (
<div>
<Child onGreet={this.greet} />
</div>
)
}
};
export class Child extends React.Component {
constructor(props) {
this.state = { value: '' };
this.handleChange = this.handleChange.bind(this);
this.eventClick = this.eventClick.bind(this);
}
handleChange(event) {
this.setState({ value: event.target.value });
}
eventClick() {
this.props.onGreet(this.state.value);
}
render() {
return (
<div>
<input type="text" value={this.state.value} onChange={this.handleChange} />
<button type="button" onClick={this.eventClick}>Submit </button>
</div>
)
}
};
You can try to utilize React's state property.
import React, { Component } from 'react';
import { render } from 'react-dom';
export class Parent extends React.Component {
constructor(props) {
this.greet = this.greet.bind(this);
this.state = {
text: [],
};
}
greet(value) {
//console.log(value);
const {text} = this.state
return this.setState({
text: text.concat(value),
});
}
render() {
return (
<div>
<Child onGreet={this.greet} />
<ul>
{this.state.text.map(x => (<li>{x}</li>))}
</ul>
</div>
)
}
};
With this, the list gets populated as the value of this.state.text changes.
i have an error in my react code, my result component is not changed after change array data, in console i just see new arrays after change input, new builded data is work, but component result isnot changed.
App.jsx
import React, { Component } from 'react'
import './App.css';
import fetch from 'isomorphic-fetch'
import Header from './Header'
import Content from './Content'
import Footer from './Footer'
class App extends Component {
constructor(props) {
super(props)
this.state = {
stripdata: null,
query: ""
}
this.query = this.query.bind(this)
}
componentWillMount() {
fetch(`http://localhost:3000/data/info.json`)
.then(results => results.json())
.then(data => {
this.setState({
stripdata: data
})
})
.catch(err => {
console.log("Didn't connect to API", err)
})
}
query(e) {
e = e.trim().toLowerCase();
this.setState({
query: e
})
}
show(data, query) {
return (query.length > 0) ?
data.filter(item => { return item.fakename.stripclub.toLowerCase().match( query ) }) :
data
}
render() {
console.log(this.show(this.state.stripdata, this.state.query))
return (
<div className="App">
<Header onQuery={this.query}/>
{
(this.state.stripdata === null) ?
<div className="loading">Loading data...</div> :
<Content onResult={ this.show(this.state.stripdata, this.state.query) }/>
}
<Footer />
</div>
);
}
}
export default App;
Content.jsx
import React, { Component } from 'react'
import Result from './Result'
class Content extends Component {
constructor(props) {
super(props);
this.state = {
stripdata: this.props.onResult
};
}
componentWillMount() {
}
render() {
return (
<div className="Content">
<Result stripdata={ this.state.stripdata }/>
</div>
);
}
}
export default Content;
Finder.jsx
import React, { Component } from 'react'
class Finder extends Component {
constructor(props) {
super(props)
this.state = {}
this.handleChange = this.handleChange.bind(this)
}
handleChange(e) {
this.props.find(e.target.value)
}
render() {
return (
<div className="Finder">
<form id="search" onSubmit="">
<span>i want</span>
<input type="text"
placeholder="type who you want"
onChange={ this.handleChange }
/>
</form>
</div>
);
}
}
export default Finder;
Header.jsx
import React, { Component } from 'react'
import Finder from './Finder'
class Header extends Component {
constructor(props) {
super(props);
this.state = {
};
this.find = this.find.bind(this);
}
find(e) {
this.props.onQuery(e)
}
render() {
return (
<div className="Header">
<div className="inner">
<h2>Find with which girl you want to spend your time !!!</h2>
<Finder find={ this.find }/>
</div>
</div>
);
}
}
export default Header;
Result.jsx
import React, { Component } from 'react'
import PersonCard from './PersonCard'
class Result extends Component {
constructor(props) {
super(props);
this.state = {
stripdata: this.props.stripdata
};
}
componentWillMount() {
}
render() {
return (
<div className="result">
{
this.state.stripdata.map((item, i) => {
return <PersonCard key={i} data={item}/>
})
}
</div>
);
}
}
export default Result;
import React, { Component } from 'react'
import Facebook from 'react-icons/lib/fa/facebook'
import VK from 'react-icons/lib/fa/vk'
import Phone from 'react-icons/lib/fa/phone'
PersonCard.jsx
class PersonCard extends Component {
constructor(props) {
super(props);
this.state = {
info: this.props.data
};
}
render() {
var now = new Date().getFullYear();
return (
<div className="PersonCard">
<div className="layer one">
<div className="side left face-image">
<img src={(this.state.info.photo) ? this.state.info.photo : ""} alt="Person Pic" />
</div>
<div className="side right info">
<p><b>Fake Name:</b> { this.state.info.fakename.stripclub }</p>
<p><b>Real Name:</b> { (this.state.info.name) ? this.state.info.name : null }</p>
<p><b>Currently Workplace:</b> { (this.state.info.address.work ) ? this.state.info.address.work : null }</p>
<p><b>Age:</b> { (this.state.info.born) ? (now - this.state.info.born.slice(0, 4)) : null }</p>
<p><br /><a href={ (this.state.info.fakename.facebook) ? this.state.info.fakename.facebook.id : null } ><icon><Facebook /></icon> { (this.state.info.fakename.facebook) ? this.state.info.fakename.facebook.user : null }</a></p>
<p><br /><a href={ (this.state.info.fakename.vk) ? this.state.info.fakename.vk.id : null }><icon><VK /></icon> { (this.state.info.fakename.vk) ? this.state.info.fakename.vk.user : null }</a></p>
<p><br /><a href={ (this.state.info.phone) ? "tel:" + this.state.info.phone : null }><icon><Phone /></icon> { (this.state.info.phone) ? this.state.info.phone : null }</a></p>
</div>
</div>
<div className="layer two">
<div className="about">
<p>{ this.state.info.physical }</p>
<p>{ (this.state.info.work_days) ? 'All Week ' + this.state.info.work_days : null }</p>
</div>
</div>
</div>
);
}
}
export default PersonCard;
Please help me with with this issue.
Try to write the Content component like this:
class Content extends Component {
render() {
return (
<div className="Content">
<Result stripdata={ this.props.onResult }/>
</div>
);
}
}
And the Result component like this also:
class Result extends Component {
render() {
return (
<div className="result">
{
this.props.stripdata.map((item, i) => {
return <PersonCard key={i} data={item}/>
})
}
</div>
);
}
}
And in the PersonCard replace every reference of this.state to this.props and remove the assignment in the constructor.
I am guessing the problem is with the assignments of props into state like in the Content component:
constructor(props) {
super(props);
this.state = {
stripdata: this.props.onResult
};
}
the constructor is probably not getting called after the input values changes.
The assumption that the constructor is getting called every time the component is rendered confuses a lot of beginner react devs...
Anyway you dont need to use state in these presentational components (https://medium.com/#dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0)
just use props.
I am trying to build a simple Todo app, however throws an error:
Please can someone help identify the error??
Error
app.min.js:9 Uncaught TypeError: Cannot read property 'data' of undefined
at Object.value [as addNewContact] (http://localhost:8888/dist/assets/js/app.min.js:9:18059)
at b.value (http://localhost:8888/dist/assets/js/app.min.js:9:19043)
at Object.f.invokeGuardedCallback (http://localhost:8888/dist/assets/js/app.min.js:3:5790)
at g (http://localhost:8888/dist/assets/js/app.min.js:3:3021)
at Object.h [as executeDispatchesInOrder] (http://localhost:8888/dist/assets/js/app.min.js:3:3241)
at l (http://localhost:8888/dist/assets/js/app.min.js:2:30755)
at n (http://localhost:8888/dist/assets/js/app.min.js:2:30881)
at Array.forEach (native)
at c (http://localhost:8888/dist/assets/js/app.min.js:3:6210)
at Object.processEventQueue (http://localhost:8888/dist/assets/js/app.min.js:2:31947
Code:
import React from 'react';
import ReactDOM from 'react-dom';
export class ContactsListApp extends React.Component {
constructor(props) {
super(props);
this.state = {
data: this.props.data
}
}
addContact(newContactObj) {
console.log(newContactObj);
var tmpStateData = this.state.data;
tmpStateData.push(newContactObj.value);
this.setState({
data: tmpStateData
});
}
render() {
return (
<div className="contact-list">
<div className="container">
<div className="row">
<div className="col-xs-12 col-sm-12 col-md-12">
<AddContactPanel addNewContact={this.addContact} />
<ContactList contacts={this.state.data} />
</div>
</div>
</div>
</div>
)
}
}
class ContactList extends React.Component {
render() {
var items = Array.prototype.map.call(this.props.contacts, function (contact, index) {
return <ContactItem name={contact.name} key={index} />
});
return (
<ul>{items}</ul>
)
}
}
class AddContactPanel extends React.Component {
constructor(props) {
super(props);
}
handleAddContact() {
var contactItem = this.refs.newContactName;
this.props.addNewContact({
"_id": (Math.random(1000 * 10) + 1),
"name": this.refs.newContactName.value,
"occupation": "myJob",
"email": "me#hotmail.com",
"telephone": "0123456789"
});
}
render() {
return (
<div className="row">
<form>
<input required ref="newContactName" type="text" name="newContactName" />
<input type="submit" name="submit" onClick={this.handleAddContact.bind(this)} />
</form>
</div>
)
}
}
class ContactItem extends React.Component {
render() {
return (
<li>{this.props.name}</li>
)
}
}
module.exports = {
contactListApp: ContactsListApp
}
Thanks in advance!
First of all in order to make the state available to the function you need to bind it. You can make use of fat-arrow function for this purpose
addContact(newContactObj) {
console.log(newContactObj);
var tmpStateData = this.state.data;
tmpStateData.push(newContactObj.value);
this.setState({
data: tmpStateData
});
}
Secondly: setting props to the initial state is an anti-pattern as suggested by react docs and you should avoid using it this way. Instead you can set the state to a prop value in the componentDidMount function like
constructor(props) {
super(props);
this.state = {
data: ''
}
}
componentDidMount() {
this.setState({data: this.props.data})
}
addContact = (newContactObj) => {
console.log(newContactObj);
var tmpStateData = this.state.data;
tmpStateData.push(newContactObj.value);
this.setState({
data: tmpStateData
});
}
I have simple update data function which currently not working:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
data: 'Initial data...'
}
this.updateState = this.updateState.bind(this);
};
updateState() {
this.setState({data: 'Data updated...'})
}
render() {
return (
<div>
<button onClick = {this.updateState}>CLICK</button>
<h4>{this.data}</h4>
</div>
);
}
}
ReactDOM.render(<App/>, document.getElementById('app'));
Below I have link to jsbin:
http://jsbin.com/vidumiroki/edit?html,js,output
You missed state in you return render function
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
data: 'Initial data...'
}
this.updateState = this.updateState.bind(this);
};
updateState() {
this.setState({data: 'Data updated...'})
}
render() {
return (
<div>
<button onClick = {this.updateState}>CLICK</button>
<h4>{this.state.data}</h4>
</div>
);
}
}
ReactDOM.render(<App/>, document.getElementById('app'));
this is 1st component as index.jsx
this is array which contains all the data.
let details=[{
id:'1',
website: 'amazon',
username:'harry',
password: '1234'
},
{
id:'2',
website: 'flipkart',
username:'nowag',
password: 'gfjh'
},
{
id:'3',
website: 'skype',
username:'king',
password: 'yesyes'
},
{
id:'4',
website: 'facebook',
username:'deep',
password: 'hellohello'
}];
class app starts here
class App extends React.Component{
constructor(props) {
super(props);
this.state= {
filter: null
};
}
setFilter(filter) {
this.setState({filter: filter})
}
render(){
error is out here that "Cannot read property 'filter' of undefined"
let filteredPassword = this.props.details.filter(
(detail) =>{
return detail.website.toLowerCase().indexOf(this.state.search)!= -1;
}
);
return (
<ul>
<Filter onUpdateFilter={this.setFilter} />
{
filteredPassword.map((detail)=>{
return <Detail item={detail} key={detail.id} />
})}
</ul>
)
}
}
export default App;
now there is another component filter.jsx
class Filter extends React.Component{
constructor(props) {
super();
this.state= {
search:'Search'
};
}
updateSearch(event) {
this.setState({search: event.target.value.substr(0,40)});
//this.props.onUpdateFilter(event.target.value.substr(0,40))
}
render() {
return (
<div>
<input type="text" defaultValue={this.state.search} onchange={this.updateSearch.bind(this)}/>
</div>
)
}
}
this is way, which i tried to run my filter, but it is not working
This is what your code should look like :
class App extends React.Component{
constructor(props) {
super(props);
this.state= {
filter: null
};
this.setFilter = this.setFilter.bind(this);
}
setFilter(filter) {
this.setState({filter: filter})
}
render(){
let filteredPassword = this.props.details.filter(
(detail) =>{
return detail.website.toLowerCase().indexOf(this.state.search)!= -1;
}
);
return (
<ul>
<Filter onUpdateFilter={this.setFilter} />
{
filteredPassword.map((detail)=>{
return <Detail item={detail} key={detail.id} />
})}
</ul>
)
}
}
export default App;
class Filter extends React.Component{
constructor(props) {
super(props);
}
updateSearch(event) {
this.props.onUpdateFilter(event.target.value.substr(0,40))
}
render() {
return (
<div>
<input type="text" defaultValue="Search" onchange={this.updateSearch.bind(this)}/>
</div>
)
}
}
If you don't pass details to the component, you need replace this.props.details to details
And replace this, because setFilter has wrong context
<Filter onUpdateFilter={this.setFilter} />
to this:
<Filter onUpdateFilter={filter => this.setFilter(filter)} />
or bind in constructor:
constructor(props) {
super(props);
this.state= {
filter: null
};
this.setFilter = this.setFilter.bind(this)
}