I have a class that contains the class Component.
When I provide an onClick prop for the to use and try to pass a function, I get the following error:
AddForm.js:74 Uncaught TypeError: _this3.props.onClick is not a function
Code:
export default class Company extends React.Component {
constructor(props) {
super(props);
this.state = {
AddOrView: <AddForm header="Add User" formFields={this.fields} />,
users: this.props.initialUsers
}
}
handleAdd() {
console.log('Hello World');
}
render() {
return (
<AddWithTitle onClick={e => this.setState({
AddOrView: <AddForm header="Add User"
formFields={this.fields}
formResponses=""
onClick={this.handleAdd} />
})
} src="blah.png">
Add User</AddWithTitle>
);
}
}
export default class AddForm extends React.Component {
render() {
return(
<button className="btn btn-primary"
formResponses={this.state.fieldValues}
onClick={() => this.props.onClick()} >
Save
</button>
);
}
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
Thank you for your help :)
You have to bind the function to your top level component for it to fire whatever you want it to fire in the onClick method.
<AddWithTitle onClick={e => this.setState({
AddOrView: <AddForm header="Add User"
formFields={this.fields}
formResponses=""
onClick={this.handleAdd.bind(this)} />
})
} src="blah.png">
Add User</AddWithTitle>
Related
I want to display a different component with each button click.
I'm sure the syntax is wrong, can anyone help me? The browser doesn't load
I would love an explanation of where I went wrong
One component (instead of HomePage) should display on the App component after clicking the button. Help me to understand the right method.
Thanks!
App.js
import React, {useState} from 'react';
import './App.css';
import Addroom from './components/Addroom.js'
import HomePage from './components/HomePage.js'
function App() {
const [flag, setFlage] = useState(false);
return (
<div className="App">
<h1>My Smart House</h1>
<button onClick={()=>{setFlage({flag:true})}}>Addroom</button>
<button onClick={()=>{setFlage({flag:false})}}>HomePage</button>
{setState({flag}) && (
<div><Addroom index={i}/></div>
)}
{!setState({flag}) && (
<div><HomePage index={i}/></div>
)}
</div>
)
}
export default App;
HomePage
import React from 'react'
export default function HomePage() {
return (
<div>
HomePage
</div>
)
}
Addroom
import React from 'react'
export default function Addroom() {
return (
<div>
Addroom
</div>
)
}
I didn't test it but as i can see it should be something like this:
<button onClick={()=>setFlage(true)}>Addroom</button>
<button onClick={()=>setFlage(false)}>HomePage</button>
{flag && (
<div><Addroom index={i}/></div>
)}
{!flag && (
<div><HomePage index={i}/></div>
)}
You need to call setFlage function with argument of Boolean saying true or false and it changes the flag variable that you want to read.
Try the following.
function App() {
const [flag, setFlage] = useState(false);
return (
<div className="App">
<h1>My Smart House</h1>
<button
onClick={() => {
setFlage(true);
}}
>
Addroom
</button>
<button
onClick={() => {
setFlage(false );
}}
>
HomePage
</button>
{flag ? <Addroom /> : <HomePage /> }
</div>
);
}
You are missing render methods and also you should use setState for reactive rendering.( when you use state variables and once value changed render method will rebuild output so this will load your conditinal component.
https://jsfiddle.net/khajaamin/f8hL3ugx/21/
--- HTML
class Home extends React.Component {
constructor(props) {
super(props);
}
render() {
return <div> In Home</div>;
}
}
class Contact extends React.Component {
constructor(props) {
super(props);
}
render() {
return <div> In Contact</div>;
}
}
class TodoApp extends React.Component {
constructor(props) {
super(props);
this.state = {
flag: false,
};
}
handleClick() {
this.setState((state) => ({
flag: !state.flag,
}));
console.log("hi", this.state.flag);
}
getSelectedComp() {
if (this.state.flag) {
return <Home></Home>;
}
return <Contact></Contact>;
}
render() {
console.log("refreshed");
return (
<div>
<h1>
Click On button to see Home component loading and reclick to load back
Contact component
</h1
<button onClick={() => this.handleClick()}>Switch Component</button>
{this.getSelectedComp()}
</div>
);
}
}
ReactDOM.render(<TodoApp />, document.querySelector("#app"));
I'm trying to pass a callback function from parent->child, but when the child component is rendered I get the error: TypeError: this.props.setCurrentWindow is not a function.
Parent component where I am trying to pass the function setCurrentWindow
class Parent extends Component {
constructor(props){
super(props);
this.setCurrentWindow = this.setCurrentWindow.bind(this);
}
setCurrentWindow(){
console.log("called")
}
render(){
return(
<Child
setCurrentWindow={this.setCurrentWindow}
/>)}
}
child component where I am trying to call setCurrentWindow
class Child extends Component{
constructor(props){
super(props)
}
render(){
return(
<div
onClick={()=>{this.props.setCurrentWindow()}}>
{this.props.children}
</div>
)}
}
Why is setCurrentWindow not being recognized as a function here?
Please check this example where I only found the difference is to have child element like <div><h1>Hello</h1></div> that was not in your code. other than this everything is working fine. When I click on the div, it writes called in console
export default class Parent extends Component {
constructor(props) {
super(props);
this.setCurrentWindow = this.setCurrentWindow.bind(this);
}
setCurrentWindow() {
console.log("called")
}
render() {
return (
<Child
setCurrentWindow={this.setCurrentWindow}
>
<div>
<h1>Hello</h1>
</div>
</Child>
)
}
}
class Child extends Component {
constructor(props) {
super(props)
}
render() {
return (
<div onClick={() => {
this.props.setCurrentWindow()
}}>
{this.props.children}
</div>
);
}
}
Try this:
parent.jsx:
class Parent extends Component {
// code omitted for brevity
handleSetWindow = () => {
//
};
render() {
return (
<div>
<Child onSetWindow={this.handleSetWindow}
/>
</div>
);
}
}
child.jsx:
class Child extends Component {
render() {
return (
<div>
<button onClick={() => this.props.onSetWindow()} >
Set
</button>
</div>
);
}
}
A stupid answer but the final solution here is that not all instances of my child components were being passed this.setCurrentWindow hence the undefined error. Durrr! Thanks for the responses!
I have a React <App> component with inside this structure:
{/*
INSIDE <APP>
<BreadCrumb>
<Chip/>
<Chip/>
<Chip/>
...
<BreadCrumb/>
<CardContainer>
<Card/> // just a clickable image
<Card/>
<Card/>
...
<Button/>
<CardContainer/>
*/}
I need a click on <Card> to activate a <Button> function, and this function should change the state of <App> as "activate" I mean that when I click on a <Card> the <Button> becomes clickable.
I have some problems to understand how pass function parents to children and set the state of a parent from inside a child.
this is my App component
class App extends React.Component {
constructor(props){
super(props)
this.state = {
activeIndex: 1
}
}
submitChoice() {
this.setState({activeIndex : this.state.activeIndex ++});
}
}
render() {
return (
<Button onClick = {this.submitChoice})/>
}
and this is the Button
class Button extends React.Component {
render() {
return(
<button
onClick = {() => this.props.onClick()}
className="button">
Continua
</button>
);
}
}
when i click on the button i receve this error
TypeError: Cannot read property 'activeIndex' of undefined
Use a property of the "Card" component to pass your callback function:
const Card = ({ onClick, id }) => {
const triggerClick = () => {
onClick(id);
};
return (
<div onClick={triggerClick}>Click the card</div>
);
};
const App = () => {
const cardClicked = id => {
console.log(`Card with id ${id} was clicked`);
//Modify App state here
};
return (
<CardContainer>
<Card onClick={cardClicked} id="card-1"/>
<Card onClick={cardClicked} id="card-2"/>
</CardContainer>
);
}
I'm new to ReactJS and I would like to communicate between my components.
When I click an image in my "ChildA" I want to update the correct item image in my "ChildB" (type attribute in ChildA can only be "itemone", "itemtwo", "itemthree"
Here is what it looks like
Parent.js
export default class Parent extends Component {
render() {
return (
<div className="mainapp" id="app">
<ChildA/>
<ChildB/>
</div>
);
}
}
if (document.getElementById('page')) {
ReactDOM.render(<Builder />, document.getElementById('page'));
}
ChildA.js
render() {
return _.map(this.state.eq, ecu => {
return (
<img src="../images/misc/ec.png" type={ecu.type_eq} onClick={() => this.changeImage(ecu.img)}/>
);
});
}
ChildB.js
export default class CharacterForm extends Component {
constructor(props) {
super(props);
this.state = {
items: [
{ name: "itemone" image: "defaultone.png"},
{ name: "itemtwo" image: "defaulttwo.png"},
{ name: "itemthree" image: "defaultthree.png"},
]
};
}
render() {
return (
<div className="items-column">
{this.state.items.map(item => (<FrameCharacter key={item.name} item={item} />))}
</div>
);
}
}
I can retrieve the image on my onClick handler in my ChildA but I don't know how to give it to my ChildB. Any hints are welcomed, thanks you!
What you need is for Parent to pass an event handler down to ChildA which ChildA will call when one of the images is clicked. The event handler will call setState in Parent to update its state with the given value, and then Parent will pass the value down to ChildB in its render method.
You can see this working in the below example. Since I don't have any actual images to work with—and to keep it simple—I've used <button>s instead, but the principle is the same.
class Parent extends React.Component {
constructor(props) {
super(props);
this.state = {
clickedItem: 'none',
};
}
render() {
return (
<div>
<ChildA onClick={this.handleChildClick}/>
<ChildB clickedItem={this.state.clickedItem}/>
</div>
);
}
handleChildClick = clickedItem => {
this.setState({ clickedItem });
}
}
const items = ['item1', 'item2', 'item3'];
const ChildA = ({ onClick }) => (
<div>
{items.map(name => (
<button key={name} type="button" onClick={() => onClick(name)}>
{name}
</button>
))}
</div>
);
const ChildB = ({clickedItem}) => (
<p>Clicked item: {clickedItem}</p>
);
ReactDOM.render(<Parent/>, document.querySelector('div'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.development.js"></script>
<div></div>
I'm making a simple todo app, where i have put in the logic to edit and delete the todos as well. I'm trying to update the parent state from child component but when i'm trying to click on delete it is throwing me an error e.preventDefault() is not a function and it is removing all of the todos here are the components:
PARENT
export default class App extends React.Component {
constructor(props){
super(props);
this.state = {
listArr: [],
}
}
deleteTodos(i) {
var lists = this.state.listArr;
lists.splice(i, 1);
this.setState({listArr: lists})
}
render() {
.......
<ToDoList {...this.state} passDeleteTodos={this.deleteTodos} />
......
}
CHILD
export class ToDoList extends React.Component {
constructor(props) {
super(props);
this.state = {
editing: false,
};
handleDelete(e, i) {
e.preventDefault();
this.props.passDeleteTodos()
}
renderDisplay() {
return(
<div>
{
this.props.listArr.map((list,i) => {
return(
<div key={i} index={i} ref="text">
<li>{list}
<div style={{float: 'right'}}>
<button className="btn btn-danger btn-xs glyphicon glyphicon-trash"
onClick={() => this.handleDelete(i)}
/>
</div>
</div>
</div>
You need to pass the event object to handleDelete function when you make use of Arrow function as done in your implementation.
You can think of an arrow function like a function that calls another function to which you need to pass the arguments. Event object is a parameter to the arrow function and you indeed need to pass this on to the handleDelete function
onClick={(e) => this.handleDelete(e, i)}
However after this change you still need to bind the deleteTodos function in the parent, since the context of this inside this function won't be that of the React class component, you can do it like
deleteTodos = (i) => {
var lists = this.state.listArr;
lists.splice(i, 1);
this.setState({listArr: lists})
}
or
constructor(props){
super(props);
this.state = {
listArr: [],
}
this.deleteTodos = this.deleteTodos.bind(this);
}
I change e.preventDefault() => e.preventDefault and bind the function.
Example
export default class App extends React.Component {
constructor(props) {
super(props)
this.state = {
listArr: [],
}
this.deleteTodos = this.deleteTodos.bind(this)
}
handleDelete(e, i) {
e.preventDefault;
this.props.passDeleteTodos()
...
}
render() {
return(
<div>
{
this.props.listArr.map((list,i) => {
return(
<div key={i} index={i} ref="text">
<li>{list}
<div style={{float: 'right'}}>
<button className="btn btn-danger btn-xs glyphicon glyphicon-trash"
onClick={(e,i) => this.handleDelete(e,i)}
/>
</div>
</div>
)}
}
</div>
You are not sending e to the correspondent method.
You could also bind the event
onClick={this.handleDelete.bind(this, i)}
Same applies for deleteTodos in the App component.
Either way you can use the same approach or bind it in the constructor:
export default class App extends React.Component {
constructor(props) {
super(props)
this.state = {
listArr: [],
}
this.deleteTodos = this.deleteTodos.bind(this)
}
...
}
doesn't behave the same way as an so you can't expect the same preventDefault call.
But your problem is you in bind the order of params change. So you're binded param becomes first in the function. See my snippet below.
const App = () => {
const _click = (externalVar, e) => {
console.log("PARAMS", externalVar, e);
};
const externalVar = 1
return (
<button onClick={_click.bind(undefined, externalVar)}>click me</button>
);
};
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
Like it says here
fun.bind(thisArg[, arg1[, arg2[, ...]]])
arg1, arg2, ... Arguments to prepend to arguments provided to the
bound function when invoking the target function.
arrow function in react doesn't need to bind to this.
But during call to the functions, for example to call this function handleDelete
handleDelete(e, i) {
e.preventDefault();
this.props.passDeleteTodos()
}
we will use synatx as:
handleDelete.bind(i)
handleDelete(e, i) {
e.preventDefault();
this.props.passDeleteTodos()
...
}
onClick={(e,i) => this.handleDelete(e,i)}
if the above code is not working properly try this.
handleDelete(i) {
this.props.passDeleteTodos()
...
}
onClick={(e,i) => {e.preventDefault(); this.handleDelete(i)}}