I'm trying to get value from my state, but the result is just [object Object], can anyone help me why this happen?
selectItems = (e) => {
if (e.target.checked) {
this.setState({
selected: e.target.value
})
} else {
return null
}
}
render(){
const { productDetail } = this.props
<input type='checkbox' id='checkbox' value={productDetail} onChange={this.selectItems} />
}
Your input element write the changes to State, but didn't reflect the changes from State to the element. That won't be helping you.
Your component also didn't provide props type checking, so that's causing to send the wrong info to this component's prop.
Hi try this approach.
selectItems = (e) => {
if (e.target.checked) {
this.setState({
selected: e.target.value
})
} else {
return null
}
}
render() {
let productDetail = [{name:"test"}];
let value = [];
productDetail.forEach(res => {
value.push(
<div>
<input
type='checkbox'
id='checkbox'
value={res.name}
onChange={this.selectItems} /> Select
</div>
)
})
return (<span>
{value}
{this.state.selected}
</span> );
}
}
Related
Can someone explain why this validation is not working properly? When I click the submit button I should check to see if the field is empty, if it is it should display the error and prevent the next page. If the form has been filled in, then no message should display and clicking the button will take you to a new screen. Currently, the error displays whether or not the field is filled in and the page does not advance in either case.
import React, { Component } from 'react'
const intialState = {
account: "",
accountError: ""
};
export class LandingPage extends Component {
state = intialState;
handleChange = event => {
this.setState({
})
}
continue = e => {
e.preventDefault();
this.props.nextStep();
}
validate = () => {
let accountError= "";
if (!this.state.name) {
accountError = "You must enter an account number!";
}
if (accountError) {
this.setState({ accountError });
return false;
}
return true;
};
handleSubmit = event => {
event.preventDefault();
const isValid = this.validate();
if (isValid) {
console.log(this.state);
this.setState(intialState);
}
};
previous = e => {
e.preventDefault();
this.props.previousStep();
}
render() {
const { values } = this.props;
const { errors } = this.props;
return (
<div>
<h1>Enter an account number</h1>
<input
type="text"
required="required"
placeholder="Enter Account Number"
autoComplete='off'>
</input>
<div className="footer">
<button onClick={this.validate}>Submit</button>
</div>
<div>
{this.state.accountError}
</div>
</div>
)
}
}
export default LandingPage;
The issue is that the name in the state was not getting any value. Fix it like below.
Change the initialState to have the name field
const intialState = {
...
...
name: ""
};
handleChange needs to set the value from the event.
handleChange = (event) => {
this.setState({ [event.target.name]: event.target.value });
};
Update the validate function to handle the case when input is typed.
validate = () => {
let accountError = "";
if (!this.state.name) {
accountError = "You must enter an account number!";
}
if (accountError) {
this.setState({ accountError });
return false;
}
this.setState({ accountError: "" });
return true;
};
Add the handleChange as the onChange to the input element.
<input
...
...
...
name="name"
onChange={this.handleChange}
></input>
Working Example
I am in new in React and I am trying to change the state when the user type some values in the inout. For a reason the component does not seem to work. Could anyone explain me why I am not succeeding in implementing this function? Thanks, Valentino
import React, { Component } from 'react';
class Stake extends Component {
state = ({
userStake: null
});
handleUserStake = (e) => {
e.preventDefault();
let newStake = e.target.value;
this.setState({
userStake: [...userStake, newStake]
})
}
render() {
return (
<div>
<form onSubmit={this.handleUserStake}>
<input
style={{
marginLeft: "40px",
width: "50px"
}}
type="text"
name="stake"
required
/>
</form>
</div >
);
}
}
export default Stake;
to accomplish a controlled input you should add the property value pointing to the respective state, and onChange that will handle its state update. for your onSubmit you use another handler specific to it. you should also fix your handleChange to update its value correctly:
class Stake extends Component {
state = ({
userStake: [],
input: ''
});
handleUserStake = (e) => {
let input = e.target.value;
this.setState({ input });
}
handleSubmit = () => {
e.preventDefault();
let newStake = this.state.input;
this.setState({
userStake: [...this.state.userStake, newStake],
input: '',
})
}
render() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<input
style={{
marginLeft: "40px",
width: "50px"
}}
type="text"
name="stake"
value={this.state.input}
onChange={this.handleUserStake}
required
/>
</form>
</div>
);
}
}
export default Stake;
You need to first get userStake from the state
handleUserStake = (e) => {
e.preventDefault();
let newStake = e.target.value;
// you need to first get it from the state before updating
const { userStake } = this.state;
this.setState({
userStake: [...userStake, newStake]
})
}
Firstly you should create constructor for your component with state and binded `handleUserStakez method.
Because you are waiting for the submit event from form you would use ref for the input:
this.inputRef = React.createRef();
ref={this.inputRef}
Full code here:
class Stake extends Component {
constructor(props) {
super(props);
this.state = {
userStake: ""
};
this.handleUserStake = this.handleUserStake.bind(this);
this.inputRef = React.createRef();
}
handleUserStake = (e) => {
e.preventDefault();
let newStake = this.inputRef.current.value;
console.log("newStake", newStake);
this.setState({
...this.state,
userStake: newStake
});
};
render() {
return (
<div>
STATE: {this.state.userStake}
<form onSubmit={this.handleUserStake}>
<input
style={{
marginLeft: "40px",
width: "50px"
}}
type="text"
name="stake"
required
ref={this.inputRef}
/>
</form>
</div>
);
}
}
this should work ...
state = {
userStake: [],
};
handleUserStake = (e) => {
e.preventDefault();
let newStake = e.target.stake.value;
this.setState((state) => ({
userStake: [...state.userStake, newStake],
}));
};
what was problem? :-
getting value you need to add NAME from target which is form to get field value. like ...
let newStake = e.target.stake.value;
getting current state value, your were just getting userStake out of nowhere so it was giving undefined error.
this.setState((state) => ({ userStake: [...state.userStake, newStake], }));
make default value to [] for userStake in state obj.
userStake: []
I think I found the solution. The problem was that I had to write [...this.state.userStake, newStake]
My objective is to change the value of the object to true or false while onchanging the checkbox.
Object contains:
{
id: '12497wewrf5144',
name: 'ABC',
isVisible: 'false'
}
Here is the code:
import React, { Component } from 'react'
class Demo extends Component {
constructor(props) {
super(props)
this.state = {
demo: {}
}
}
componentDidMount() {
axios
.get('/api/random')
.then(res => {
this.setState({ demo: res.data?.[0] })
})
.catch(error => {
console.log(error)
})
}
render() {
return (
<div>
<h1>{this.state.demo.name}</h1>
<input type="checkbox" value={this.state.demo.value} />
</div>
)
}
}
export default Demo
I don't know what to write in onchange method for checkbox to only change the value within the object.
Can anyone help me in this query?
<input
type="checkbox"
value={this.state.demo.value}
onChange={(event) => {
this.setState((prevState) => ({
...prevState,
demo: { ...prevState.demo, isVisible: event.target.checked }
}));
}}
/>
Given your state ends up looking like
this.state = {
demo: {
id: "12497wewrf5144",
name: "ABC",
isVisible: "false",
value: false
}
};
You can create a change handler as such
changeHandler = e => {
e.preventDefault();
const { checked } = e.target;
this.setState(prevState => ({
...prevState, // <-- spread existing state
demo: {
...prevState.demo, // <-- spread existing demo
value: checked, // <-- save the input's checked value
}
}))
}
Attach the changeHandler to the onChange event callback
<input
type="checkbox"
onChange={this.changeHandler}
value={this.state.demo.value}
/>
Ciao, you could use onClick event like this:
...
handleClick = (e, data) => {
const demo = { ...this.state.demo };
demo.isVisible = !demo.isVisible;
this.setState({ demo });
}
...
<input type="checkbox" value={this.state.demo.value} onClick={((e) => this.handleClick(e, data))}/>
...
I need a little help with my project. I think it is almost done, but I don't know how to finish...
So, I want to build app with input, select and button. Into input u can write for example, mettalica and after click on button app renders list with all songs, titles and tabTypes(guitar tabs). The problem is that i want to get info from select and render only that songs which includes for example player tabs.
Sandbox Code: https://codesandbox.io/s/react-example-ys6py?fontsize=14&hidenavigation=1&theme=dark
class Search extends React.Component {
state = {
searchValue: "",
songs: [],
musicTabs: [
'Dowolne',
'Bass',
'Player',
'Chords',
'Guitar'
],
result: ''
};
handleOnChange = event => {
this.setState({ searchValue: event.target.value });
};
handleSelectChange = (event) => {
this.setState({
result: event.target.value
})
console.log(this.state.result)
}
handleSearch = () => {
this.makeApiCall(this.state.searchValue);
};
makeApiCall = async searchInput => {
let api_url = `https://www.songsterr.com/a/ra/songs/byartists.json?artists=${searchInput}`;
const response = await fetch(api_url);
const songs = await response.json();
this.setState({ songs });
};
render() {
return (
<div>
<Header />
<input
name="text"
type="search"
placeholder="Search..."
onChange={event => this.handleOnChange(event)}
value={this.state.SearchValue}
/>
<Select optionValue={ this.state.musicTabs } change={ this.handleSelectChange } value={ this.state.result } />
<br />
<button onClick={this.handleSearch}>Search</button>
{this.state.songs ? (
<div>
{
this.state.songs.map((song, index) => (
<div key={index} className="lists">
<h1>Artist: <span>{song.artist.name}</span></h1>
<h2>Song title: <span>{song.title}</span></h2>
<ol>
<b>Available tabs:</b>
{song.tabTypes.map((tab, index) =>
<li key={index}> {song.tabTypes[index]} </li>
)}
</ol>
</div>
))
}
</div>
) : (
<p>Something</p>
)}
</div>
);
}
}
const Select = (props) => {
const { optionValue, change } = props;
const valueMusicTabs = optionValue.map((musicTab, index) => {
return <option name={ optionValue[index] } key={ index }> { optionValue[index] } </option>
})
return (
<>
<select onChange={ change }>
{ valueMusicTabs }
</select>
</>
)
};
Thanks for help guys!
I think you did everything right, just used the wrong prop
<Select optionValue={ this.state.musicTabs } onChange={ this.handleSelectChange } value={ this.state.result } />
the change prop on the Select component should just be changed to onChange since it's a default event it will be passed with the event to your handleChange method
I checked the codesandbox, everything was working right. this.setState is an asynchronous function. So, if you will console.log after this.setState chances are your will not log updated value. You can do it like this with a callback function.
handleSelectChange = (event) => {
this.setState({
result: event.target.value
}, () => console.log(this.state.result))
}
If you want to filter you can do that by making a function like:
filterSongs = selected => {
return songs.filter(song => song.tabTypes === selected);
}
and After that modify your handleSelectChange as:
handleSelectChange = (event) => {
let songs = filterSongs(event.target.value);
this.setState({
result: event.target.value,
toDisplay: songs
}, () => console.log(this.state.result))
}
and finally in your JSX:
return (
<>
{toDisplay.map((song, index) => {
return <p key={index}>{song.toString()}</p>
})}
</>
);
If I understand correctly. you want to get the results from API based on selected values of input and select.
as I can see you are only passing the param from input nothing from select.
handleSearch = () => {
this.makeApiCall(this.state.searchValue);
};
makeApiCall = async searchInput => {
let api_url = `https://www.songsterr.com/a/ra/songs/byartists.json?artists=${searchInput}`;
const response = await fetch(api_url);
const songs = await response.json();
this.setState({ songs });
};
The new call will be
let api_url = `https://www.songsterr.com/a/ra/songs/byartists.json?artists=${searchInput}&tabTypes=${selectValue}`;
I do not know how what are the parameters this API accepts.
Thanks for answers! I have last question, where I have to use method to filter that rendered list. If I select "Player" I want to render only that songs, which inlcudes "Player" tab in tabTypes. I still can't get it. I can't do it by changing API link.
I'm new to react, and I'm working on a small project that uses a search bar to find data that I've gotten from my database.
The code for this component is below:
import React, { Component } from 'react';
class BodyData extends Component {
state = {
query: '',
data: [],
}
handleInputChange = () => {
this.setState({
query: this.search.value
})
this.filterArray();
}
getData = () => {
fetch(`http://localhost:4000/restaurants`)
.then(response => response.json())
.then(responseData => {
// console.log(responseData)
this.setState({
data:responseData
})
})
}
filterArray = () => {
var searchString = this.state.query;
var responseData = this.state.data
if(searchString.length > 0){
// console.log(responseData[i].name);
responseData = responseData.filter(l => {
console.log( l.name.toLowerCase().match(searchString));
})
}
}
componentWillMount() {
this.getData();
}
render() {
return (
<div className="searchForm">
<form>
<input type="text" id="filter" placeholder="Search for..." ref={input => this.search = input} onChange={this.handleInputChange}/>
</form>
<div>
{
this.state.data.map((i) =>
<p>{i.name}</p>
)
}
</div>
</div>
)
}
}
export default BodyData;
So basically, I want to update the state as I type in the query text, and have the restaurant names I've mapped be reduced till a match is found.
From what I understood, this.state.data will be filtered as I type in my query in the search bar. However when I map out this.state.data, I get the whole list of restaurants instead of what I want to see.
Ive been through a bunch of tutes, and I'm not exactly sure how to go about doing that.
Can anyone help me with this please? Any other comments on the code are also welcome. I'm here to learn :)
Thank you!
You could keep an additional piece of state called e.g. filteredData that contains all elements in data that include your query in the name, and then render that.
Example
class BodyData extends React.Component {
state = {
query: "",
data: [],
filteredData: []
};
handleInputChange = event => {
const query = event.target.value;
this.setState(prevState => {
const filteredData = prevState.data.filter(element => {
return element.name.toLowerCase().includes(query.toLowerCase());
});
return {
query,
filteredData
};
});
};
getData = () => {
fetch(`http://localhost:4000/restaurants`)
.then(response => response.json())
.then(data => {
const { query } = this.state;
const filteredData = data.filter(element => {
return element.name.toLowerCase().includes(query.toLowerCase());
});
this.setState({
data,
filteredData
});
});
};
componentWillMount() {
this.getData();
}
render() {
return (
<div className="searchForm">
<form>
<input
placeholder="Search for..."
value={this.state.query}
onChange={this.handleInputChange}
/>
</form>
<div>{this.state.filteredData.map(i => <p>{i.name}</p>)}</div>
</div>
);
}
}
Here is the code that will work for you
import React, { Component } from 'react';
class BodyData extends Component {
state = {
query: '',
data: [],
searchString:[]
}
handleInputChange = (event) => {
this.setState({
query: event.target.value
},()=>{
this.filterArray();
})
}
getData = () => {
fetch(`http://localhost:4000/restaurants`)
.then(response => response.json())
.then(responseData => {
// console.log(responseData)
this.setState({
data:responseData,
searchString:responseData
})
})
}
filterArray = () => {
let searchString = this.state.query;
let responseData = this.state.data;
if(searchString.length > 0){
// console.log(responseData[i].name);
responseData = responseData.filter(searchString);
this.setState({
responseData
})
}
}
componentWillMount() {
this.getData();
}
render() {
return (
<div className="searchForm">
<form>
<input type="text" id="filter" placeholder="Search for..." onChange={this.handleInputChange}/>
</form>
<div>
{
this.state.responseData.map((i) =>
<p>{i.name}</p>
)
}
</div>
</div>
)
}
}
export default BodyData;
There are few changes which is needed.
Set State is worked asynchronous.SO, to avoid it use arrow function when you need to do something immediately after set state.
there are 2 different keyword in es6 instead of var. Let and Const . use them instead of var.
There is no need of ref in input. you can directly get value of input by event.target.value
Enjoy Coding!!
setState method is asynchronous and it has second parameter - callback that is called when the state is applied.
You need to change handleInputChange methods.
handleInputChange = () => {
this.setState({
query: this.search.value
}, this.filterArray)
}
Few pointers I'll like to show-
setState({}) function is asynchronous, you'll have to either use functional setState and call filteredArray method as a callback. Or, call filteredArray at render, which is where your values will be updated and be reflected.
Your filterArray method is not returning / setting the filtered list of data. So what you type, even though it is getting filtered, it is not getting set / returned anywhere.