I want to change the text of a button when I press it.
This is what I want to achieve: https://codepen.io/gaearon/pen/xEmzGg?editors=0010 , but I can't get my code to work (newbie).
class ObjectKeyDisplay extends Component {
constructor(props) {
super(props)
this.state = {
open: false
}
this.handleClick = this.handleClick.bind(this)
}
handleClick() {
this.setState(prevState => ({
open: prevState.open
}))
}
renderInner() {
if (!this.props.value) return <td className = "inactive" > < /td>
if (!this.state.open && this.props.schema.type === 'belongs_to')
return <td onClick={(e) => this.setState({open: !this.state.open})}>
<button onClick={this.handleCLick}>
{this.state.open ? 'OFF' : 'ON'}
</button>
</td>
}
Here's my code and as you might have seen I want to toggle the text OFF and ON when pressing the button. I can add more code if needed. Really grateful for all the support I can get.
Here is what you are looking for:
handleClick() {
const open = !this.state.open;
this.setState({open})
}
The bug is in handler:
this.setState(prevState => ({
open: !prevState.open
}))
You are setting it to the same value, as it was before.. with !bool you can switch the value
Additionally the condition is not making any sense:
if (!this.state.open && this.props.schema.type === 'belongs_to')
return <td onClick={(e) => this.setState({open: !this.state.open})}>
<button onClick={this.handleCLick}>
{this.state.open ? 'OFF' : 'ON'}
</button>
</td>
This means only if the condition is met, you component will return something..
true === (!this.state.open && this.props.schema.type === 'belongs_to')
Related
when i clicked on close button the val will immedietly changes to Fruit. how to do that?
for example
Apple close
Grapes close
Pineapples close
otherwise how can we set the state cancel is true based on the index.
I mean if i clicked on Apple close button, only that index value will true other are false. can we do this?
here is the sample code
constructor(){
super();
this.state={
cancel: false;
}
}
<table>
<tr>
{
products.map((val, index)=>{
<td>{val} <button>closeIcon</button></td>
});
}
</tr>
</table>
if anyone help me how to solve this problem
Here i have asked two questions.
Outof these you can answer one question.
I believe this is what you're looking for, only one fruit can be closed
export default class Test extends React.Component {
constructor() {
super();
this.state = {
cancel: false,
products: [
{
name: "Apple",
closed: false
},
{
name: "Grapes",
closed: false
},
{
name: "Pineapples",
closed: false
}
]
};
this.onClick = this.onClick.bind(this);
}
onClick(e) {
this.setState((s) => ({
...s,
products: s.products.map((p) => ({
...p,
closed: p.name === e.target.name
}))
}));
}
render() {
return (
<table>
<tr>
{this.state.products.map((val, index) => {
return (
<td>
{val.closed ? "CLOSED" : "OPEN"} {val.name} {" "}
<button name={val.name} onClick={this.onClick}>
closeIcon
</button>
</td>
);
})}
</tr>
</table>
);
}
}
Take a look https://codesandbox.io/s/silly-swirles-wfnks?file=/src/App.js
To make all can close:
onClick(e) {
this.setState((s) => ({
...s,
products: s.products.map((p) =>
p.name === e.target.name ? { ...p, closed: true } : p
)
}));
}
https://codesandbox.io/s/tender-glade-6vg6b
You need to have a seperate state for Button component in that is being rendered by map. In this way you'll be able to setState for every individual Button component.
Wrap your button in a seperate component
export default class ButtonComponent extends React.Component{
constructor(){
super();
this.state={
cancel: false;
}
}
onCancel = () => {
this.setState({...this.state, cancel: true})
}
render(){
return(
<td>{val} <button onClick={this.onCancel}>closeIcon</button>
</td>
)
}
}
render(){
return(
<table>
<tr>
{
products.map((val, index)=>{
<ButtonComponent key={index} />
});
}
</tr>
</table>
)
}
You are not returning the anything from your map function. After fixing it, simply updating the state with this.setState on onClick would do
<tr>
{
products.map((val, index)=>{
return (<td>{val} <button>closeIcon</button></td>);
});
}
</tr>
See the jsfiddle here, https://jsfiddle.net/qzmu5307/
Edit: If you just want to remove an item from the list on close button, you can simply remove that item from the array in the state (for now i am doing so by searching the value in the array, but this is usually a bad practice. Assign them some identifiers for this uprose).
Having some trouble with state management in react-sound. I have a dynamic grid of buttons - when mousing over a button, audio plays as an example of what that button represents, and when mousing off, it stops. Right now, it's running into problems when you click on a button and the screen reloads another array as a grid of buttons - when you do that and then navigate back to the former screen, the behavior is REVERSED, so that audio plays when you mouse OFF the button and stops when you mouse ON. I've tried several things that I thought should work, including triggering toggleHoverState() on click, but nothing has worked so far. Any advice? Code below:
class Screen extends React.Component {
constructor(props) {
super(props);
this.state = {displayArray: taxonomyArray,
isHovering: false};
this.handleClick = this.handleClick.bind(this);
this.handleMouseHover = this.handleMouseHover.bind(this);
}
handleMouseHover() {
this.setState(this.toggleHoverState);
}
toggleHoverState(state) {
return {
isHovering: !state.isHovering,
};
}
handleClick(updatedArray = taxonomyArray) {
//this.setState(this.toggleHoverState);
this.setState({
displayArray: updatedArray,
});
}
render () {
return (
this.state.displayArray.map(item =>
<Col key={Math.random()} span={4} xs="auto" sm="auto" md="auto" lg="auto">
<a key={Math.random()} data-tip={item.description ? (item.description) : console.log('null description')}>
{ (item.audio && this.state.isHovering) && <div><Sound url={item.audio} playStatus={Sound.status.PLAYING} volume={50}/></div> }
<Button
className='trigger'
key={Math.random()}
variant= {item.child === undefined ? "outline-secondary" : (item.child === null ? "secondary" : "primary") }
onMouseEnter={this.handleMouseHover}
onMouseLeave={this.handleMouseHover}
onClick={ () => ( item.child === null ? console.log('nope') : ( item.child === undefined ? this.handleClick(arrayVisits.pop()) : (arrayVisits.push(this.state.displayArray), this.handleClick(item.child))) ) }
>
{item.name}
</Button>
</a>
<ReactTooltip className='extraClass' delayHide={0} effect='solid' type="info" multiline={true}/>
<div> </div>
</Col>
)
);
}
}
This logic here is very strange:
handleMouseHover() {
this.setState(this.toggleHoverState);
}
toggleHoverState(state) {
return {
isHovering: !state.isHovering,
};
}
Why not just write
handleMouseHover() {
this.setState({ isHovering: !this.state.isHovering })
}
But if you're still having problems, I would write some very explicit functions for onMouseEnter and onMouseLeave to reduce confusion:
onMouseEnter={ () => { this.setState( isHovering: true ) } }
onMouseLeave={ () => { this.setState( isHovering: false) } }
Let me know if that solves it
Is the page actually reloading, or is it a BrowserRouter?
It sounds like, if it's a BrowserRouter, that state isn't being reset. Try adding:
componentDidMount () {
this.setState({isHovering:false})
}
I am trying to implement a textbox similar to google flights.
so I have built a react autocomplete prototype.
but in that i am facing an issue.
right now in the google flights textbox when I click on the textbox it shows all the rersults without typing anything.
but in my case if I type something only it will show the results.
so the textbox I added a props onPress in that I am calling an event handleEvent.
but nothing printing inside the method.
can you tell me how to achieve so that in future I will fix it myself.
providing my code snippet and sandbox below
https://codesandbox.io/s/xp6x167kq4
handleEvent = () => {
console.log("I was clicked");
alert("I was clicked");
};
render() {
const {
onChange,
onClick,
onKeyDown,
state: {
activeSuggestion,
filteredSuggestions,
showSuggestions,
userInput
}
} = this;
let suggestionsListComponent;
if (showSuggestions && userInput) {
if (filteredSuggestions.length) {
suggestionsListComponent = (
<ul class="suggestions">
{filteredSuggestions.map((suggestion, index) => {
let className;
// Flag the active suggestion with a class
if (index === activeSuggestion) {
className = "suggestion-active";
}
return (
<li className={className} key={suggestion} onClick={onClick}>
{suggestion}
</li>
);
})}
</ul>
);
} else {
suggestionsListComponent = (
<div class="no-suggestions">
<em>No suggestions, you're on your own!</em>
</div>
);
}
}
return (
<Fragment>
<input
type="text"
onChange={onChange}
onKeyDown={onKeyDown}
value={userInput}
onPress={this.handleEvent}
//onPress={this.handleEvent}
/>
{suggestionsListComponent}
</Fragment>
);
}
I believe this is because in your initial state you've written
this.state = {
activeSuggestion: 0,
filteredSuggestions: [],
showSuggestions: false,
userInput: '',
};
and later you run
if (showSuggestions && userInput) but on an initial click userInput still equals '' which equates to false. Underneath again, you run if (filteredSuggestions.length) which also equates 0 because when nothing is typed the array filteredSuggestions is empty.
console.log('' == true) => false also
console.log([].length == true) => false
As part of a technical test, I've been asked to write an autocomplete input in React. I've done this but I'd now like to add the functionality of navigating up and down the rendered list with the arrow keys. I've done some extensive Googling and found nothing React specific apart from npm packages.
To be clear, I'm looking for something like this but for React: https://www.w3schools.com/howto/howto_js_autocomplete.asp
All I basically need is the arrow button functionality, I've got everything else working fine.
Cheers
Here's an example that I tried but couldn't get working.
export default class Example extends Component {
constructor(props) {
super(props)
this.handleKeyDown = this.handleKeyDown.bind(this)
this.state = {
cursor: 0,
result: []
}
}
handleKeyDown(e) {
const { cursor, result } = this.state
// arrow up/down button should select next/previous list element
if (e.keyCode === 38 && cursor > 0) {
this.setState( prevState => ({
cursor: prevState.cursor - 1
}))
} else if (e.keyCode === 40 && cursor < result.length - 1) {
this.setState( prevState => ({
cursor: prevState.cursor + 1
}))
}
}
render() {
const { cursor } = this.state
return (
<Container>
<Input onKeyDown={ this.handleKeyDown }/>
<List>
{
result.map((item, i) => (
<List.Item
key={ item._id }
className={cursor === i ? 'active' : null}
>
<span>{ item.title }</span>
</List.Item>
))
}
</List>
</Container>
)
}
}
And here is my code:
class Search extends Component {
constructor(props) {
super(props);
this.state = {
location: '',
searchName: '',
showSearch: false,
cursor: 0
};
}
handleKeyPress = e => {
const { cursor, searchName } = this.state;
// arrow up/down button should select next/previous list element
if (e.keyCode === 38 && cursor > 0) {
this.setState(prevState => ({
cursor: prevState.cursor - 1
}));
} else if (e.keyCode === 40 && cursor < searchName.length - 1) {
this.setState(prevState => ({
cursor: prevState.cursor + 1
}));
}
};
render() {
const { searchName, location } = this.state;
return (
<div className="Search">
<h1>Where are you going?</h1>
<form id="search-form" onSubmit={this.handleSubmit}>
<label htmlFor="location">Pick-up Location</label>
<input
type="text"
id="location"
value={location}
placeholder="city, airport, station, region, district..."
onChange={this.handleChange}
onKeyUp={this.handleKeyUp}
onKeyDown={this.handleKeyPress}
/>
{this.state.showSearch ? (
<Suggestions searchName={searchName} />
) : null}
<button value="submit" type="submit" id="search-button">
Search
</button>
</form>
</div>
);
}
Code that renders the list from the restful API:
.then(res =>
this.setState({
searchName: res.data.results.docs.map(array => (
<a href="#">
<div
key={array.ufi}
className="locations"
>
{array.name}
</div>
</a>
))
})
);
Since you are defining a function as handleKeyDown(e) {...} the context this is not pointing to the context of class instance, the context will be supplied by onKeyDown (and I suppose it's window as this)
So, you have 2 ways to go:
declare your function as handleKeyDown = (e) => {...}
bind handleKeyDown context to component instance like onKeyDown={this.handleKeyDown.bind(this)}
Also, don't forget that you may want a mod items.length counter, meaning when your press down and the last item is already selected, it would go to the first item.
Your api usage with storing markdown into the state is just a terrible thing to do. You don't have access to these strings anymore, instead save it as a plain array. Pass it where you need it, and use it to create jsx there.
Also, you don't use cursor from your state at all.
I have a button that changes the active state onClick:
render() {
return(
<SomeButton
onClick={e => this.handleClick(e)}
id={someId}
activeStatus={someId === this.state.active ? "active" : "not active"}
/>
)
}
The function that changes the state:
handleClick(e) {
e.preventDefault();
this.setState({ active: e.currentTarget.id });
}
The state:
this.state = {
active: null
};
The button that receives the activeStatus props:
export default function SomeButton({ activeStatus }) {
console.log(activeStatus);
return (
// button jsx code
);
}
However, every time I click on the button (I have 3 instances of that button on the page), the activeStatus console.log shows:
I click on button 1:
active
not active
not active
I click on button 2:
active
active
not active
I click on button 3:
active
active
active
I was expecting that the status would toggle depending on the active button which is clicked.
What am I missing?
You can set the state in an array:
this.state = {
active: [false, false, false] // or just: []
};
handleClick(e) {
e.preventDefault();
const activeState = [false, false, false]; // or just: []
activeState[e.currentTarget.index] = true;
// button index ^^
this.setState({ active: activeState });
}
And just pass the activeStatus to the active state:
activeStatus={this.state.active}
Inside your component, bind the active state:
<button className={ activeStatus[0] ? 'active' : 'not-active' }>...</button>
<button className={ activeStatus[1] ? 'active' : 'not-active' }>...</button>
<button className={ activeStatus[2] ? 'active' : 'not-active' }>...</button>
I'd use e.target.id instead of e.currentTarget.id and if the button ids are static, then you could put them into your state and use the id to update a buttonState object (one of several ways to handle it).
Working example: https://codesandbox.io/s/olmn9k08m5
Some notes:
Keep your state consistent (if it's a string, keep it a string, if
it's an array, keep it any array...etc -- in the example below
buttonState is an object and stays an object).
Also, you don't need e.preventDefault() unless you're submitting a
form or trying to block functionality.
Always specify the button's type ("button" or "submit")
ShowButton.js
import React, { Component } from "react";
import SomeButton from "./SomeButton";
const buttons = ["button1", "button2", "button3"];
export default class App extends Component {
state = {
buttonState: {
button1: "inactive",
button2: "inactive",
button3: "inactive"
}
};
handleClick = e => {
const { id } = e.target; // id="button1","button2" or "button3"
this.setState(prevState => ({
buttonState: {
...prevState.buttonState, // spread out object
[id]: prevState.buttonState[id] === "active" ? "inactive" : "active" // use the [id] as an object property (ex: "button1") and set the property's value to "active" or "inactive"
}
}));
};
render = () => (
<div className="container">
<h1>Controlling Active Buttons</h1>
{buttons.map(id => (
<SomeButton
key={id}
id={id}
handleClick={this.handleClick}
activeStatus={this.state.buttonState[id]}
/>
))}
</div>
);
}
SomeButton.js
import React from "react";
export default ({ activeStatus, handleClick, id }) => (
<div style={{ marginBottom: 20 }}>
<button
type="button"
style={{ minWidth: 150 }}
className={`uk-button ${
activeStatus === "active" ? "uk-button-primary" : null
}`}
id={id}
onClick={handleClick}
>
{activeStatus}
</button>
</div>
);