I'm learning React and I'm trying to make a button which will change on click. It must be ether "Succeed" or "Not succeed" depending on the server's answer. This is what I've done so far. My question is - what the handleClick function must do? Should I use transition by toggling classes?
Thanks!
class Btn extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handlenClick.bind(this);
}
handleClick() {
???
}
render() {
const succeed = (
<div>
<ButtonToolbar>
<Button bsStyle="primary" bsSize="large">Succeed</Button>
</ButtonToolbar>
</div>
)
const notsucceed = (
<div>
<ButtonToolbar>
<Button bsStyle="primary" bsSize="large">Not succeed</Button>
</ButtonToolbar>
</div>
)
return (
<div onClick={this.handleClick.bind(this)}>
{this.state ? succeed : notsucceed}
</div>
)
}
};
You need to implement the state.
For example: https://codesandbox.io/s/313vmr23k6
class Btn extends React.Component {
constructor(props) {
super(props);
this.state = {
succeed: false
};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(previousState => {
return {
succeed: !previousState.succeed
};
});
}
render() {
const succeed = (
<div>
<button bsStyle="primary" bsSize="large">Succeed</button>
</div>
)
const notsucceed = (
<div>
<button bsStyle="primary" bsSize="large">Not Succeed</button>
</div>
)
return (
<div onClick={this.handleClick.bind(this)}>
{this.state.succeed ? succeed : notsucceed}
</div>
)
}
};
You would call your api in there and set the state depending if the call fails or succeeeds. For this your api call must return a Promise. Something like:
handleClick() {
Api.call()
.then((response) => { this.setState({ succeed: true }); })
.catch((error) => { this.setState({ succeed: false }); })
}
Related
When I run my current code it produces a button for each post in a local JSON file and if I click on the button it expands/contracts. I want to have a button that opens or closes all the posts but I'm unsure how to achieve this, my logic is that since externalData is an array of Post components, handleClick should simply be calling its own function but I get the error element.setOpenStatus is not a function when I press the Open All button.
function Post(props) {
const [openStatus, setOpenStatus] = useState(true);
if (openStatus) {
return (
<button onClick={() => setOpenStatus(false)}>
<p>Title: {props.post.title}</p>
<p>User: {props.post.user}</p>
<p>Time: {props.post.time}</p>
<p>Content: {props.post.content}</p>
<hr />
</button>
);
}
return (
<button onClick={() => setOpenStatus(true)}>
<p>Title: {props.post.title}</p>
<p>User: {props.post.user}</p>
<p>Time: {props.post.time}</p>
<hr />
</button>
);
}
class AllPosts extends React.Component {
constructor(props) {
super(props);
this.state = {
externalData: [],
};
this.handleClick = this.handleClick.bind(this);
this.renderPost = this.renderPost.bind(this);
}
renderPost(element) {
return (
<Post
key={element.title}
post={element}
/>
)
}
checkIfExisting(post, key, value) {
return post[key] === value;
}
// HERE things are going wrong
handleClick() {
this.state.externalData.forEach(element => {
element.setOpenStatus({ openStatus: false });
});
}
render() {
this.props.data.forEach((element) => {
if (!this.state.externalData.some(
(post) => this.checkIfExisting(post, "key", element.title)
)) {
this.state.externalData.push(this.renderPost(element))
}
})
return (
<div>
<h1>using local json file</h1>
<button onClick={this.handleClick}>Open All</button>
<div>
{this.state.externalData}
</div>
</div>
);
}
}
export default AllPosts;
I'm trying to return a component when I click on a button.
(a delete button with a confirmation popup) I've tried some examples I found online but none really worked for me.
Here is my code:
class DeleteTask extends React.Component {
handleClick() {
return <TaskDeleteModal />
}
render() {
return (
<div>
<button type="button" className={styles.deletetask} onClick={() => this.handleClick()}>Verwijderen</button>;
</div>
)
}
}
Thanks for reading, I hope you can assist me.
It did not work because the return <TaskDeleteModal /> of handleClick does not add <TaskDeleteModal /> to your render function.
You need to add <TaskDeleteModal /> to render function and control it visibility by a state:
Try the following code:
class DeleteTask extends React.Component {
this.state = {
showModal: false
}
handleClick() {
this.setState({showModal: true})
}
render() {
return (
<div>
<button type="button" className={styles.deletetask} onClick={() => this.handleClick()}>Verwijderen</button>;
{/* In TaskDeleteModal you might have a button, when you click on that button call this.setState({showModal: false}) to hide the modal */}
{this.state.showModal && <TaskDeleteModal />}
</div>
)
}
}
class DeleteTask extends React.Component {
this.state = {
showModal: false
}
handleClick() {
this.setState({showModal: true})
}
render() {
return (
<div>
<button type="button" className={styles.deletetask} onClick={() => this.handleClick()}>Verwijderen</button>;
{/* In TaskDeleteModal you might have a button, when you click on that button call this.setState({showModal: false}) to hide the modal */}
{this.state.showModal && <TaskDeleteModal />}
</div>
)
}
}
My code is
class Com extends React.Component {
constructor(props) {
super(props);
this.state = {is_clicked: false};
}
render() {
let sub_com1 = () => {
return (
<div>Input1:<input/></div>
);
};
let sub_com2 = () => {
return (
<div>Input2:<input/></div>
);
};
return (
<div>
<div>
{this.state.is_clicked ? sub_com1() : sub_com2()}
</div>
<button onClick={()=>{
let is_clicked=this.state.is_clicked;
this.setState({is_clicked: !is_clicked});
}}>
Click me
</button>
</div>
);
}
}
and the live display: codepen.
In this code, I use conditional rendering in Com's render method.
What I expect
Each time I click the button, the input area should be cleared since it is rendered to another component
What I met
Each time I click the button, the "input1" or "input2" label has changed, but the input area is not cleared.
To fix this issue you have to add key attributes to your input elements, change the code be like this and it will work:
class Com extends React.Component {
constructor(props) {
super(props);
this.state = {is_clicked: false};
}
render() {
let sub_com1 = () => {
return (
<div>Input1:<input key={1} id='A' /></div>
);
};
let sub_com2 = () => {
return (
<div>Input2:<input key={2} id='b' /></div>
);
};
return (
<div>
<div>
{this.state.is_clicked ? sub_com1() : sub_com2()}
</div>
<button onClick={()=>{
let is_clicked=this.state.is_clicked;
this.setState({is_clicked: !is_clicked});
}}>
Click me
</button>
</div>
);
}
}
ReactDOM.render(
<Com/>,
mountNode,
);
The following article discuss it in more depth and why its important to have key attribute for elements:
full article: keys-in-children-components-are-important
Key is not really about performance, it’s more about identity (which
in turn leads to better performance). Randomly assigned and changing
values do not form an identity Paul O’Shannessy
I'm trying to make a toggle content button with React. But I can only get it to open, not to close when I click on it again. Can someone please take a look and let me know what I need to change within the code to accomplish it?
Here's what I have so far:
class Test extends React.Component {
constructor(props) {
super(props)
this.state = {
activeLocation: 0,
}
}
changeActiveLocation = (activeLocation) => {
this.setState({
activeLocation: activeLocation,
});
}
render() {
const activeLocation = company.locations[this.state.activeLocation];
return (
{company.locations.map((location, index) => (
<div className="test-item">
<div className="test-item-container" onClick={() => {this.changeActiveLocation(index)}}>
<div className="test-item-header">
<h3>Text goes here!</h3>
<a><FontAwesomeIcon icon={(this.state.activeLocation === index) ? 'times' : 'chevron-right'} /></a>
</div>
</div>
</div>
))}
)
}
}
Thank you!
You're setting the active location to be the same location that you've clicked already so the this.state.activeLocation === index is always true. I would refactor the locations to their own component with an isOpen state value that gets updated when the location is clicked. So like the following:
// test class
class Test extends React.Component {
constructor(props) {
super(props)
this.state = {
activeLocation: 0,
}
}
changeActiveLocation = (activeLocation) => {
this.setState({
activeLocation: activeLocation,
});
}
render() {
const activeLocation = company.locations[this.state.activeLocation];
return (
{company.locations.map((location, index) => (
<LocationItem location={location} onClick={() => this.changeActiveLocation(index)} />
))}
)
}
}
// LocationItem
class LocationItem extends React.Component {
state = { isOpen: false };
handleClick = () => {
this.setState(prevState => { isOpen: !prevState.isOpen});
// call parent click to set new active location if that's still needed
if(this.props.onClick) this.props.onClick;
}
render() {
return <div className="test-item">
<div className="test-item-container" onClick={this.handleClick}>
<div className="test-item-header">
<h3>Text goes here!</h3>
<a><FontAwesomeIcon icon={(this.state.isOpen ? 'times' : 'chevron-right'} /></a>
</div>
</div>
</div>
}
}
export default class player extends React.Component {
constructor(...args) {
super(...args);
this.state = {
shoot: 0
};
}
shootis the variable i'm trying to change in the function shooter, and display later in <h1>.
shooter() {
this.setState({ shoot: Math.floor(Math.random() * Math.floor(3)) });
console.log("hello");
}
render() {
return (
<div>
<h1>{this.state.shoot}</h1>
<button onClick={() => this.shooter}>shoot it</button>
</div>
);
}
}
the <h1> is not changing as the state changes, won't the state change as shooter() fires? and doesn't it update the <h1>.
any help much appreciated. :-)
Change the line
<button onClick={() => this.shooter}>shoot it</button>
To
<button onClick={() => this.shooter()}>shoot it</button>
Bind your class method shooter in your constructor, in order to use it like this onClick={this.shooter}.
You can find a further explanation here.
export default class player extends React.Component {
constructor(...args) {
super(...args);
this.state = {
shoot: 0
};
this.shooter = this.shooter.bind(this);
}
render() {
return (
<div>
<h1>{this.state.shoot}</h1>
<button onClick={this.shooter}>shoot it</button>
</div>
);
}
}