This is my code
My state
this.state = {
loading: true,
weather: [],
cityName: [],
selectedOption: '',
}
My call api
const getAPIcityName = Axios.get('http://dataservice.accuweather.com/locations/v1/topcities/100?').then((res) => {
console.log('res' + res);
this.setState({ cityName: res.AdministrativeArea.LocalizedName });
}, (error) => {
console.log('error', error)
});
}
And here i wont to do the Select the name of the city
handleChange(selectedOption) {
this.setState({ selectedOption });
console.log(selectedOption);
}
render() {
let options = this.state.cityName.map((cityName) => {
return cityName.AdministrativeArea.LocalizedName;
})
return (
<div class="container">
<h1 for="Search">Search</h1>
<form>
<Select
name="form-field-name"
value={this.state.value}
onChange={this.handleChange}
options={options}
/>
And here it works
{/* <select class="custom-select custom-select-lg mb-3">
{this.state.cityName.map(cityName => <option key={cityName.Key}>{cityName.AdministrativeArea.LocalizedName}</option>)}
</select> */}
And this is the Error
Unhandled Rejection (TypeError): Cannot read property 'LocalizedName' of undefined
If my understanding is correct, you are using react-select.
react-select needs options array in the following format,
const options = [
{ value: '', label: '' },
{ value: '', label: '' },
...
]
Your options should be in above format.
As your data is coming from an API, you need to first check if you have data in state and then only iterate over the state to get options
let options = [];
if(this.state.cityName && this.state.cityName.length > 0){
options = this.state.cityName.map((cityName) => {
return {value: cityName.AdministrativeArea.LocalizedName, label: cityName.AdministrativeArea.LocalizedName};
})
}
Related
I am needing help with a simple dropdown menu. I am trying to render this dropdown, then take the value of the input and put it in the database. However I get this error every single time. Any clues as to why?
Here is the file and how I am trying to render it. The error pops up on the handleInputChange function.
public state = {
isDirty: false,
selectedFile: [] as any[],
well: new IWell(),
wellId: this.props.match.params.wellId,
wellPageTitle: 'New Well'
};
constructor(props: any) {
super(props);
this.WellsStore = this.props.stores.WellsStore;
this.MessageStore = props.stores.MessageStore;
this.params = this.props.match.params;
this.handleInputChange = this.handleInputChange.bind(this);
}
private handleInputChange(event: any) {
const category = this.state.well.files;
category[event.target.name] = event.target.value;
this.setState({
category,
});
}
public renderDropdown = (category: any) => () => {
return(
<FormGroup >
<EInput
type="select"
name="category"
id="category"
value={this.state.well.files}
onChange={this.handleInputChange(category)}
>
<option value=""/>
<option value="Not Categorized">Not Categorized</option>
<option value="Signed Documents">Signed Documents</option>
<option value="Unsigned Documents">Unsigned Documents</option>
<option value="3rd Party Documents">3rd Party Documents</option>
<option value="General Well Info">General Well Info</option>
</EInput>
</FormGroup>
);
}
private formatWellFiles = () => {
const files = this.state.well.files;
const headers = [
"File Name",
"Category",
"Size",
"Uploaded By",
"Upload Date",
"Download",
];
const rows = files.map(f => {
return [
{
content: f.name
},
{
content: this.renderDropdown(f.category),
type:'render'
},
{
content: this.renderSize(f.size),
sortItem: Number(f.size),
type: 'render'
},
{
content: f.createUser
},
{
content: f.createDate
},
{
content: this.renderDownload(f),
type: 'render',
},
];
});
return { headers, rows };
}
Change this line:
onChange={this.handleInputChange(category)}
to:
onChange={event => this.handleInputChange(event)}
I'm trying to achieve making a suspend user button via updating the values of the user the status to Suspended, but the problem is the status is defined but other values are undefined did I do something wrong or is there any way to update the values to make the other variable like a name not required?
This is what I mean:
This is my code:
const User = (props) => (
<>
<DropdownButton id="dropdown-basic-button" title="Action">
<Dropdown.Item>
<a
href="user"
onClick={() => {
props.onSubmit(props.user[0]);
}}
>
<i className="fas fa-trash"></i> Suspend
</a>
</Dropdown.Item>
</DropdownButton>
</>
);
export default class Users extends Component {
constructor(props) {
super(props);
this.onSubmit = this.onSubmit.bind(this);
this.state = { users: [] };
}
componentDidMount() {
axios
.get("http://localhost:5000/users/")
.then((response) => {
this.setState({ users: response.data });
})
.catch((error) => {
console.log(error);
});
}
onSubmit(id) {
const user = {
name: this.state.name,
password: this.state.password,
email: this.state.email,
storeName: this.state.storeName,
storeUrl: this.state.storeUrl,
date: this.state.date,
status: "Suspended",
};
console.log(user);
axios
.post("http://localhost:5000/users/update/" + id, user)
.then((res) => console.log(res.data));
}
userList(currentuser) {
return (
<User
user={currentuser}
key={currentuser[0]}
onSubmit={this.onSubmit}
/>
);
}
render() {
const columns = [
{
name: "_id",
options: {
display: false,
},
},
{
name: "name",
label: "Name",
options: {
filter: true,
sort: true,
},
},
{
name: "Action",
options: {
customBodyRender: (value, tableMeta, updateValue) => {
return <>{this.userList(tableMeta.rowData)}</>;
},
},
},
];
const { users } = this.state;
return (
<>
<MUIDataTable data={users} columns={columns} />
</>
);
}
}
You didn't define nor set the User's individual attributes' values in the state! So, no wonder they show up as undefined, when you try to read them...
The simplest solution would be:
onSubmit(id) {
//let user = this.state.users.find(user => user.id === id); // find by id
let user = this.state.users[id]; // find by index
if (user) {
user.status = 'Suspended';
console.log(user);
axios
.post("http://localhost:5000/users/update/" + id, user)
.then((res) => console.log(res.data));
}
}
I have updated the Code.
Here I have a functional Select Autocomple showing the list of records from DB "Register". When selecting a Code, the Name value is automatically renamed.
The same thing I want to do but with the not with , I want to call more than two values like this in the image and in select is only Label and Value
Capture: [1]: https://i.stack.imgur.com/ELf1a.png
class Register extends Component {
state = {
status: "initial",
data: [],
name:'',
code:''
}
componentDidMount = () => {
this. getInfo()
}
getInfo= async () => {
try {
const response = await getAll('register')
console.log(response.data)
this.setState({
status: "done",
data: response.data
});
} catch (error) {
this.setState({
status: "error"
});
}
};
handleChange = (selectedOption) => {
this.setState({
selectedOption,
name: selectedOption.value
});
render() {
//show Name and code on Select from Register
const data = this.state.data.map( st => ({value: st.Name, label: st.Code}));
return (
<Container>
<RowContainer margin="1px" >
<ColumnContainer margin="10px">
<h3>Info</h3>
<label>Code</label>
<Select
width='215px'
value={selectedOption}
onChange={this.handleChange}
options={data}
name={"Code"}
/>
<label>Name</label>
<Input
width='150px'
type="text"
name={"Name"}
placeholder="Name"
value={this.state.name} />
</ColumnContainer>
</RowContainer>
</Container>
)
}
};
export default Register;
You want to know how change the state for <input/>
try this
constructor(props){
super(props)
this.state = {
status: "initial",
data: [],
codigo: "",
nombre: ""
}
}
handleChange(event){
let stateUpdate = this.state;
stateUpdate[event.target.name] = event.target.value}
this.setState(stateUpdate);
}
render() {
const data = [...this.state.data];
return (
<Container>
<RowContainer margin="1px" >
<ColumnContainer margin="10px">
<h3>Info</h3>
<label>Codigo</label>
<Input
name="codigo"
width='150px'
type="text"
placeholder="Digite el codigo"
value={data.codigo } ref="codigo" />
<label>Nombre</label>
<Input
name="nombre"
width='150px'
type="text"
placeholder="Nombre completo"
value={this.state.nombre} />
</ColumnContainer>
</RowContainer>
</Container>
)
}
As I an New to ReactJS.
What i am doing is when i type is any field State should be update in particular field -
As This is my LoginComponet and Setting small Form -
import React, { Component } from 'react';
import '../css/style.css';
export class LoginCompoent extends Component {
constructor(props) {
super(props);
this.state = {
field: {
phone: {
value: '',
validations: [],
errors: []
},
password: {
value: '',
validations: [],
errors: []
}
}
};
this.handelChangeEvent = this.handelChangeEvent.bind(this);
}
componentDidMount() {
}
handelChangeEvent(event) {
this.setState({
field: {
[event.target.id]: {
'value': event.target.value
}
}
});
}
render() {
console.log(this.state);
return (
<div className="loginMainDiv" >
<div className="">
<input className="login_inp" placeholder="Mobile Number"
value={this.state.field.phone.value}
onChange={this.handelChangeEvent}
type="text" name="phone" id="phone"
/>
<input className="login_inp" placeholder="Password"
value={this.state.field.password.value}
onChange={this.handelChangeEvent}
type="password" name="password" id="password"
/>
<button className="login_btn" >Login Safely</button>
</div>
</div>
);
}
}
Expected Result - on console.log(this.state);
when I type 9 in phone field -
field: {
phone: {
value: '9',
validations: [],
errors: []
},
password: {
value: '',
validations: [],
errors: []
}
}
Getting Result -
field: {
phone: {
value: '9'
}
}
I don't know why all fields are suddenly hidden when i update only phone field. ?
Because of this password is not setting in the form. ERROR - this.state.field.password is undefined ???
Deep merging issues, as you set a name property to your input, this should work:
this.setState(prevState => ({
field: {
...prevState.field,
[event.target.name]: {
'value': event.target.value
}
}
}));
In your handleChangeEvent function, you are updating the value of the field in the state:
this.setState({field: {
[event.target.id]: {
'value': event.target.value
}
}})
This will obviously overwrite the existing value of the field.
In your case, I would recommend using the callback function inside the setState. Please see the docs.
For example, if you want to update the value of the phone but also you want the value of the password to remain unchanged, You could do something like this:
handleChangeEvent = (event) => {
this.setState((prevState) => {
return {field: {
[event.target.id]: event.target.value,
...prevState.field
}
};
});
}
As I have tried all the Above answers but facing the error.
ERROR- Uncaught TypeError: Cannot read property 'id' of null on this.setState( prevState => ( {} ) ).
The Problem was - the reference of event are not maintain in async call that's why event.target is becoming null and getting above Error.
I got the concept of event.persist() which helps to maintain all the references of the event and make the Wrapper to the browser event with async calls.
You can go to this Article Reference
The dropdown looks and works fine, but will not update a new selection and I get the following error message:
Warning: Use the `defaultValue` or `value` props on <select> instead of setting `selected` on <option>.
Selected is not set on <option> as far as I'm aware, so it must be set by material-ui's component. Anyway, if I change value into defaultValue, I get the following error message:
aterial-UI: the `value` property is required when using the `Select` component with `native=false` (default).
I thought it was a problem in Material-ui itself, but their example works fine, although there are no parent/child components in the example like mine.
Example:
https://codesandbox.io/s/7yk922om7x
My code (shortened for brevity):
constructor(props) {
super(props)
this.state = {
languageValues: {
htmlFor: 'lstLanguages',
value: 'english',
input: <Input name="language" id="lstLanguages"/>,
options: [
{ value: 'dutch', text: 'Nederlands' },
{ value: 'french', text: 'Français' },
{ value: 'english', text: 'English' },
{ value: 'german', text: 'Deutsch' }],
helperText: 'Choose your language',
}
}
}
handleChange = event => {
event.preventDefault();
this.setState({ [event.target.name]: event.target.value });
}
render() {
return (
<div>
<h2 id="speechTitle">Speech Settings</h2>
<hr/>
<FormGroup column='true'>
<DropDown
dataToFill={ this.state.languageValues }
onChange={ this.handleChange.bind(this) }
/>
Dropdown.js:
const DropDown = ({dataToFill}) => {
const menuItemValueList = dataToFill.options.map((item, i) => {
return <MenuItem value={ item.value } key={ i }>{ item.text }</MenuItem> //Always provide a key
})
return (
<FormGroup column='true'>
<FormControl>
<InputLabel htmlFor={ dataToFill.htmlFor }>Languages</InputLabel>
<Select
defaultValue={ dataToFill.value }
input={ dataToFill.input }
>
{ menuItemValueList }
</Select>
<FormHelperText>{ dataToFill.helperText }</FormHelperText>
</FormControl>
</FormGroup>
);
}
EDIT 1
I think I have found the problem: The handleChange function expects [event.target.name] but the value that needs changing is nested in the state, I'm not sure how I can access it...
Event handler code:
handleChange = event => {
this.setState({ [event.target.name]: event.target.value })
}
Nested state object:
languageValues: {
htmlFor: 'lstLanguages',
value: 'english',
input: <Input name="language" id="lstLanguages"/>,
options: [
{ value: 'dutch', text: 'Nederlands' },
{ value: 'french', text: 'Français' },
{ value: 'english', text: 'english' },
{ value: 'german', text: 'German' }
],
helperText: 'Choose your language',
},