Recently I started to learn ReactJS with help of tutorials and I've run into an error I can't find solution for by myself. One of the first projects I decided to do is To-do list and when trying to pass "handleChange" function as a prop to my component I get this error TypeError: Cannot read property 'handleChange' of undefined.
Here is my full code of App class so you can see what I'm trying to do:
import React from 'react';
import './App.css';
import Content from "./Content"
import ToDoItems from "./ToDoItems"
class App extends React.Component {
constructor() {
super()
this.state = {
items: ToDoItems
}
this.handleChange = this.handleChange.bind(this)
}
handleChange() {
console.log("Change!")
}
render() {
const items = this.state.items.map(function(item){
return (<Content key={item.id} todo={item.item} checked={item.completed} handleChange={this.handleChange}/>)
})
return (
<div>
{items}
</div>
)
}
}
export default App;
I'm getting my data from file called ToDoItems and trying to pass them as props into Content component. Everything is working fine until I try to pass the function handleChange().
I must be doing something wrong. Any help would be appreciated.
The problem is here,
const items = this.state.items.map(function(item){
return (<Content key={item.id} todo={item.item} checked={item.completed} handleChange={this.handleChange}/>)
})
When ur using non-array function it binds this and others stuff to its own protoype. Meaning ur this.handleChanges this actually refers to function, instead of class
Try using this,
const items = this.state.items.map((item) => {
// ^^^^^^^^^^^
return (<Content key={item.id} todo={item.item} checked={item.completed} handleChange={this.handleChange}/>)
})
as Arrow functions don't bind this or any other stuff. so this should now refer to the class
Related
Hi developers I'm just a beginner in React.js. I tried to print props by passing from parent to child.
This is app.js file
import React from "react";
import Hooks from "./components/ReactHooks1";
import Hooks2 from "./components/ReactHooks2";
const App = () => {
return (
<div>
<h1>
Welcome to React App
</h1>
<Hooks2 title2={"Welcome"}/>
</div>
)
}
export default App
This is child component file
import React from 'react';
const Hooks2 = (props) => {
console.log(props);
}
export default Hooks2;
I just try to print props but it shows an empty object. what am I doing wrong please help me on this
You should return something or null to parent component from child, when you're using it in parent component. This will solve your problem
export const Hooks2 = (props) => {
console.log(props);
return <></>;
}
#Rasith
Not sure why would you want to do this, but if you're trying to pass a child component that would print something to the console. In this case you need to destructure the component's props. Here's an article about it from MDN.
This is how I would do it:
const CustomComponent = ({title}) => {
console.log(title)
}
const App = () => {
return (
<>
<h1>Hello World</h1>
<CustomComponent title={"Welcome"}/>
</>
);
};
For the title to be printed to the console, no need to add a return statement to the child component. Again, not sure why you would do this, but there you go.
Well trying to console.log title certainly would not work because what you are passing is called title2. Also your child component is not returning anything.
First, you have to return anything from your child component( even a fragment )
You can access title2 in the child component with any of these methods:
1- using props object itself
const Hooks2 = (props) => {
console.log(props.title2);
return;
}
2- you can also destructure props in place to access title2 directly
const Hooks2 = ({title2}) => {
console.log(title2);
return ;
}
You have to use destructuring in your ChildComponent, to grab your props directly by name:
const Hooks2 = ({title2}) => {
console.log(title2);
}
You can read a little bit more about it in here: https://www.amitmerchant.com/always-destructure-your-component-props-in-react/
I'm trying to practice mapping array objects and i cannot for the life of me get this to display on scrimba mini-browser. I can console.log the array object but that's all. Am i overlooking anything? Thanks.
import React from 'react'
import man from './menitem.js'
class App extends React.Component{
constructor(){
super()
this.state = {Men:man}
}
render(){
const newman = this.state.Men.map(item => item={item} )
const newman1 = newman.toString(newman)
return(<div>
<p>{newman}</p>
</div>)
}
}
export default App
Screenshot of application
The function that you're passing to .map isn't getting you what you need. It should be something more like:
const newman = this.state.Men.map(item => (<p key={item}>{item}</p>));
then in your return statement:
return (
<div>
{newman}
</div>
);
// ClientDisplay.js
class ClientDisplay extends Component {
...
render() {
const {activeClient} = this.props
console.log(activeClient); // This works fine
const clientGroupMenu = (
<div>
<SelectMenu
defaultValue={activeClient.groupName}
...
)
return (
<div>{clientGroupMenu}</div>
)
}
}
export default ClientDisplay
// View.js
export class View extends Component {
...
render(){
return (
<ClientDisplay
{...this.props}
/>
)
}
...
}
As you can see the line console.log(activeClient) logs the correct data.
However I get an error on defaultValue={activeClient.groupName}
index.es.js:1 Uncaught TypeError: Cannot read property 'props' of null
I also get the same error if I use defaultValue={this.props.activeClient.groupName}
Does anyone know why I cannot access these properties from within this component clientGroupMenu.
Thanks
Moving ClientGroupMenu into a stateless functional component might help.
const ClientGroupMenu = ({activeClient}) => {
const {groupName} = activeClient
return (
<div>
<SelectMenu
defaultValue={groupName}
...
)
}
class ClientDisplay extends Component {
...
render() {
const {activeClient} = this.props
console.log(activeClient); // This works fine
return (
<div><ClientGroupMenu activeClient={activeClient} /></div>
)
}
}
Here is sample format like below you should use super() inside constructor :
class ClientDisplay extends Component {
constructor(props) {
super(props);
}
[...]
}
If you are getting same error then Use self.props instead of this.props everywhere!
Issue is probably because of destructuring assignment.
Use const activeClient declaration instead of const {activeClient}
Refer https://itnext.io/using-es6-to-destructure-nested-objects-in-javascript-avoid-undefined-errors-that-break-your-code-612ae67913e9 for more details about destructuring assignment.
When const {activeClient} = this.props is used, the actual object's value is copied within activeClient. You have to use defaultValue={activeClient} instead of defaultValue={activeClient.groupName}
When const activeClient = this.props is used,this.props is copied within activeClient. You have to use defaultValue={activeClient.groupName} in that case.
Sorry, I'm new to React and asked a similar question earlier, but changed the form of my code. I am trying to get a state value in a const react class.
Here in my Article.js
function changeClassName(childData) {
console.log("GETS HERE!");
this.setState({
dynamicClassName: childData
});
}
const Articles = ({ data, isLoading, error }) => {
console.log(data);
console.log(isLoading);
const article_wrapper = data.nodes || [];
if (error) {
return <p>{error.message}</p>;
}
if (isLoading) {
return <p>Loading ...</p>;
}
return (
<div className="article">
{article_wrapper.map( article =>
<div key={article.node.nid} className="article-main-display">
<h1 className="title" dangerouslySetInnerHTML={createMarkup(article.node.title)}/>
<div className="img-div"><img src={article.node.field_image.src} /></div>
<ControlForm parentMethod={changeClassName} />
<div dangerouslySetInnerHTML={createMarkup(article.node.field_user_hsk_level)} />;
<div className="field-name-field-chinese">
<div dangerouslySetInnerHTML={createMarkup(article.node.chinese)} />;
</div>
</div>
)}
</div>
);
}
Here in my ControlForm.js
Part of the render:
<div className="form-item form-type-select form-group">
<label className="control-label">Font Size</label>
<select
value={this.state.value}
onChange={this.handleSizeSelect}
id="font-size"
className="form-control form-select"
>
<option value="0">Small</option>
<option value="1">Normal</option>
<option value="2">Large</option>
<option value="3">XL</option>
</select>
</div>
And the class initiation looks like this:
class ControlForm extends Component {
constructor() {
super();
this.state = { toggleActive: false, sizeSelect: "0", speed: 1.3, volume: .6};
this.onToggle = this.onToggle.bind(this);
this.handleSpeedChange = this.handleSpeedChange.bind(this);
this.handleVolumeChange = this.handleVolumeChange.bind(this);
this.handleSizeSelect = this.handleSizeSelect.bind(this);
}
When I try to use this, I get this error:
TypeError: this.setState is not a function
However, anytime I try to convert const Articles = ... into a formal class X extends Component structure, I get a bunch of other errors.
How can I get state into this component successfully? I have been banging my head against a wall all day and I can't figure out a way to do this.
If you are using const then your file should be of .ts extension. To access the state in .ts, you need to define the type of the state in it. Please refer to this example of how you can do that:
[Reactj, typescript Property 'setState' is missing in type
Otherwise, if you want to work with .jsx then I would suggest you drop the const and declare the state outside the constructor.
First of all, your Articles is not a React Component, that's why you cannot use setState function, then your function changeClassName
isn't declared in the React.Component, that's why you see this.setState is not a function. try this:
class Article extends React.Component {
changeClassName = () => {
//function body
}
//your codes...
}
if you seeing this.setState is not a function, most of the time it just because you do not bind your function. when declaring your function in React class, try just using es6 arrow function like:
yourFunction = (args) => {
this.setState({
//.....
});
}
then you do not need mannualy bind your function in constuctor anymore
Your problem begins with this whole block of code:
function changeClassName(childData) {
console.log("GETS HERE!");
this.setState({
dynamicClassName: childData
});
Is this a React component? If so, is a functional component or a class based component?
What I am getting at is that you need to create a class-based React component like so:
class App extends React.Component {
render() {
return (
<div>
</div>
);
}
}
export default App;
Now, you will notice, once you have a class-based React component, you must include a render() method or else you will get an error. What you return inside of it is project specific.
You also need to create a class-based component so you can initialize state like so:
class App extends React.Component {
state = { images: [] };
render() {
return (
<div>
</div>
);
}
}
export default App;
In this case I have set an initial state inside my App component of images to be an empty array.
Then only within that class can you update your state via this.setState({ images: response.data.results }); for example.
This is probably going to be something really simple. But I am having hard time figuring out what is wrong with how my react component is written. Here is the component code.
import React, { Component, PropTypes } from 'react';
import styles from './Menu.css';
import SubMenu from './SubMenu';
import classNames from 'classnames/bind';
let cx = classNames.bind(styles);
export default class Menu extends Component{
static propTypes ={
menuData:PropTypes.array.isRequired
};
constructor(props){
super(props);
this.state = {menuOpenedLabel:""};
};
menuClick(label){
this.state.menuOpenedLabel = label;
};
render(){
let menus = this.props.menuData.map(function(menuItem){
let handleClick = this.menuClick.bind(this,menuItem.label);
return (<li key={menuItem.label}>
<a onClick={handleClick}>{menuItem.label}</a>
<SubMenu subMenu={menuItem.submenu} isVisible={this.state.menuOpenedLabel === menuItem.label}/>
</li>);
});
return (<nav>
<ul className={styles.menu}>{(menus)}</ul>
</nav>);
}
}
This is the error that I get in chrome.
Uncaught TypeError: Cannot read property 'menuClick' of undefined
At first I thought it was because of using this inside of the map function, but apparently that this code is correct. Based on this link.
https://facebook.github.io/react/tips/expose-component-functions.html
Any thoughts?
Ok I figured it out! there is a second parameter to map(), that controls what the value of this is.
let menus = this.props.menuData.map(function(menuItem){
let handleClick = this.menuClick.bind(this,menuItem.label);
return (<li key={menuItem.label}>
<a onClick={handleClick}>{menuItem.label}</a>
<SubMenu subMenu={menuItem.submenu} isVisible={this.state.menuOpenedLabel === menuItem.label}/>
</li>);
}, this);
Your component is fine, but map stuff can be confusing to look at sometimes. I find this a useful chunk of code, maybe it will help you even though you already figured it out:) Just a way of organizing a map and you get the index, too.
render() {
const { stuffs } = this.state;
return (
<div>
{stuffs.map((stuff, i) => {
return(
<Components key={i} funStuff={stuff.fun} />
);
})}
</div>
)
}