I want to create an axios post request that sends the id's of a bull and a heifer chosen by a user to my server to calculate traits (in this case milk production) for their offspring. I'm trying to trigger it after the submit button is clicked. I think I'm not sending the id's as properly formatted params for the server to process.
import React, { Component} from 'react';
import axios from 'axios';
class Dropdown extends Component {
constructor (props) {
super(props)
this.handleInputChange = this.handleInputChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.state = {
bullId: '',
heiferId: ''
}
}
//this updates state with new bull & heifer
handleInputChange(event) {
const target = event.target;
const value = target.value;
target.clicked = target.value;
const name = target.name;
console.log(target.name)
;
this.setState({
[name]: value
});
console.log(this.state);
}
handleChange = (event) => {
var bull = event.target.value
var heifer = event.target.value
console.log(heifer)
console.log(bull)
};
onSubmit(e) {
e.preventDefault();
const pairing = {
heifer: this.state.heiferId,
bull: this.state.bullId
}
console.log(pairing)
axios.post('http://localhost:8000/traits/:bullId/:heiferId', pairing)
.then(res => console.log(res.data));
this.setState({
bullId:"",
heiferId:""
})
}
render() {
return (
<div>
<form>
<label>Bulls
<select
name={"bullId"}
value ={this.state.bullId}
onChange= {this.handleInputChange}>
<option value="5defc2b5b9283d6de054e0f0">Buddy</option>
<option value="5defc2b5b9283d6de054e0f1">Cooper</option>
<option value="5defc2b5b9283d6de054e0f2">Maxwell</option>
<option value="5defc2b5b9283d6de054e0f3">Gus</option>
<option value="5defc2b5b9283d6de054e0f4">Paul</option>
<option value="5defc2b5b9283d6de054e0f5">Phil</option>
</select>
</label>
<br />
<label>Heifers
<select
name={"heiferId"}
value={this.state.heiferId}
onChange= {this.handleInputChange}>
<option value="5defc49cb9283d6de054e0f6">Sally</option>
<option value="5defc49cb9283d6de054e0f7">Patches</option>
<option value="5defc49cb9283d6de054e0f8">Maxine</option>
<option value="5defc49cb9283d6de054e0f9">Peach</option>
<option value="5defc49cb9283d6de054e0fa">Paula</option>
<option value="5defc49cb9283d6de054e0fb">Flower</option>
</select>
</label>
</form>
<button onClick={this.onSubmit}>submit</button>
</div>
)}
}
export default Dropdown;
Heifer.findOne({_id: req.params.heiferId}).then(function(heifer){
Bull.findOne({_id: req.params.bullId}).then(function(bull){
console.log(bull);
console.log(heifer);
let heiferMilkProduction = heifer.milkProduction;
let bullMilkProduction = bull.milkProduction;
if (heiferMilkProduction > bullMilkProduction) {
heiferMilkProduction += heiferMilkProduction * .1
bullMilkProduction -= bullMilkProduction * .1
} else {
bullMilkProduction += bullMilkProduction * .1
heiferMilkProduction -= heiferMilkProduction * .1
};
const calfTraits = {
bullMilkProduction,
heiferMilkProduction
}
res.send(calfTraits);
})
})
});```
You want something like
axios.post(`http://localhost:8000/traits/${this.state.bullId}/${this.state.heiferId}`)
The :bullId syntax in a string does nothing in react, you have to build the string like any other regular string. Its used in express for the routes as a template.
You need to embedded the value of 'bullId' and 'heiferId' in your url you are using to fetch data instead of the string.
onSubmit(e) {
e.preventDefault();
const { bullId, heiferId } = this.state;
axios.post(`http://localhost:8000/traits/${bullId}/${heiferId}`, {})
.then(res => console.log(res.data));
this.setState({
bullId:"",
heiferId:""
})
}
Related
I'm trying to become a front-end developer, so I'm creating a project with companies info. I tried to find on YouTube and here, but still I couldn't understand.
I want to use on Change to show the result, but How I pass the option value to the variable?
import React, { Component } from "react";
class BusinessCard extends Component {
constructor(props) {
super(props);
this.state = {
loading: true,
company: null,
};
}
async componentDidMount() {
let companyCod = "MSFT"; // I want receive the option value here
let companyUrl =
"https://www.alphavantage.co/query?function=OVERVIEW&symbol=" +
companyCod +
"&apikey=YOUR-API-KEY";
let response = await fetch(companyUrl);
let data = await response.json();
this.setState({ company: data, loading: false });
}
render() {
if (this.state.loading) {
return <div>loading</div>;
}
return (
<div>
<select>
<option value="MSFT">MSFT</option>
<option value="AAPL">AAPL</option>
<option value="IBM">IBM</option>
</select>
<h1>Company: {this.state.company.Name}</h1>
<h1>Symbol: {this.state.company.Symbol}</h1>
</div>
);
}
}
You could put the countryCode in your component state, and move the componentDidMount code into a separate function that you call both in componentDidMount and when the select changes.
Example
import React, { Component } from "react";
export default class BusinessCard extends Component {
constructor(props) {
super(props);
this.state = {
loading: true,
company: null,
companyCode: "MSFT"
};
}
loadCompany = async (companyCode) => {
let companyUrl =
"https://www.alphavantage.co/query?function=OVERVIEW&symbol=" +
companyCode +
"&apikey=YOUR-API-KEY";
let response = await fetch(companyUrl);
let data = await response.json();
this.setState({ company: data, loading: false });
}
componentDidMount() {
this.loadCompany(this.state.companyCode);
}
handleChange = (e) => {
const companyCode = e.target.value;
this.setState({ companyCode });
this.loadCompany(companyCode);
};
render() {
if (this.state.loading) {
return <div>loading</div>;
}
return (
<div>
<select
value={this.state.companyCode}
onChange={this.handleChange}
>
<option value="MSFT">MSFT</option>
<option value="AAPL">AAPL</option>
<option value="IBM">IBM</option>
</select>
<h1>Company: {this.state.company.Name}</h1>
<h1>Symbol: {this.state.company.Symbol}</h1>
</div>
);
}
}
I have several select element generated by a map. Aside from usingĀ jQuery to access the dom elements is there a way to get all the selected values onChange
changed = () => {
// Keep track of all the selected options
}
[1,2,3].map(value => (
<select onChange={changed}>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>)
Whenever I select an option I would like to keep track of the option selected in an array. If in the first select I chose 1 then the second one 2 I'd like to have an array [1,2] representing the options picked. If I then select the third option to be 3 then the new array should be [1,2,3].In this case I want three separate select and I want to keep track the options selected in each
Assume you use hooks in your code. This should be like
import React, { useState, useEffect } from "react";
const App = () => {
useEffect(() => {
console.log("selections: ", selections);
});
const [selections, setSelections] = useState({});
const changed = (value, e) => {
setSelections({ ...selections, [`${value}`]: e.target.value });
};
return (
<div>
{[1, 2, 3].map(value => (
<select key={value} onChange={e => changed(value, e)}>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
))}
</div>
);
};
export default App;
UPDATE: I updated my solution, sorry for missunderstand your questions, in case of multi dropdown list, your state should construct this way:
{ "1": 1, "2": 3, "3": 1}
Key is dropdown identifier and value is the selected option for it.
I've written examples using both React class and functional component for you.
If you want to use select with multiple values, you will have to set select multiple attribute to true. Note that select is very difficult to style and you may consider using a custom Dropdown instead.
import React from 'react';
import ReactDOM from 'react-dom';
class ClassExample extends React.Component {
state = {
value: [],
}
handleOnChange = (e) => {
const { value: selectedValue } = e.target;
const { value } = this.state;
const newValue = [].concat(value);
const index = newValue.findIndex(v => v === selectedValue);
if (index > -1) {
newValue.splice(index, 1);
} else {
newValue.push(selectedValue);
}
this.setState({ value: newValue });
}
render() {
const { value } = this.state;
return (
<div>
<select
value={value}
multiple
onChange={this.handleOnChange}
>
{[1, 2, 3].map(v => <option key={v} value={v}>{v}</option>)}
</select>
<pre>
{JSON.stringify(value, null, 2)}
</pre>
</div>
)
}
}
const FunctionExample = () => {
const [value, setValue] = React.useState([]);
const handleOnChange = (e) => {
const { value: selectedValue } = e.target;
const newValue = [].concat(value);
const index = newValue.findIndex(v => v === selectedValue);
if (index > -1) {
newValue.splice(index, 1);
} else {
newValue.push(selectedValue);
}
setValue(newValue);
}
return (
<div>
<select
value={value}
multiple
onChange={handleOnChange}
>
{[1, 2, 3].map(v => <option key={v} value={v}>{v}</option>)}
</select>
<pre>
{JSON.stringify(value, null, 2)}
</pre>
</div>
)
}
const App = () => (
<>
<label>
Class : <ClassExample />
</label>
<label>
Function : <FunctionExample />
</label>
</>
)
const rootElement = document.getElementById('root');
ReactDOM.render(<App />, rootElement);
Here is a working demo: https://codesandbox.io/s/react-controlled-multiple-select-g7shd?fontsize=14&hidenavigation=1&theme=dark
I need to have an edit button to edit the users first name, last name from the api but only update the input in local state. I've done a lot of research but can't find exactly what I'm looking for. I'm trying not to bring in other libraries (other than lodash possibly?). I've found a lot of other examples but its bringing in other libraries. Any suggestions would help (even on the code I have currently to help clean it up a bit.)
import React, { Component } from "react";
import axios from "axios";
import User from './User'
class App extends Component {
constructor(props) {
super(props);
this.state = {
users: [],
searchTerm: '',
alphabetical: 'az'
};
this.handleChange = this.handleChange.bind(this);
}
componentDidMount() {
axios.get("https://randomuser.me/api/?results=20")
.then(response => {
console.log(response.data.results);
this.setState({ users: response.data.results });
})
.catch(error => {
console.log(error);
});
}
handleChange(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
render() {
let sortedUsers;
if (this.state.alphabetical === "az") {
console.log("sorted");
sortedUsers = this.state.users.sort((a, b) =>
a.name.first > b.name.first ? 1 : -1
);
}
let filteredUsers = sortedUsers;
if (this.state.searchTerm)
filteredUsers = this.state.users.filter(u =>
u.name.first.startsWith(this.state.searchTerm) || u.name.last.startsWith(this.state.searchTerm)
);
const userNames = filteredUsers.map(u => {
return <User
key={u.email}
name={u.name.first}
last={u.name.last}
image={u.picture.medium}
email={u.email}
city={u.location.city}
state={u.location.state}
cell={u.cell}
/>;
});
return (
<div>
<form onSubmit={this.handleSubmit}>
<label>
Search for user:
<input
type="text"
name="searchTerm"
value={this.state.searchTerm}
onChange={this.handleChange}
/>
</label>
<input type="submit" value="Submit" />
</form>
<select
name="alphabetical"
value={this.state.alphabetical}
onChange={this.handleChange}>
<option selected value="az">
A to Z
</option>
<option value="za">Z to A</option>
</select>
{userNames}
</div>
);
}
}
export default App
I have an input field that i would like to update that users first name when you click submit for that specific user. right now i have an alert in handleSubmit to just see if its working. and it is but i want it to update the actual users name.
Displays Users on separate cards. would like the edit button to work for each user.
class User extends Component {
constructor(props) {
super(props);
this.state = {
names: ''
}
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.input = React.createRef();
}
handleChange(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
handleSubmit(event) {
alert('A name was submitted: ' + this.input.current.value);
event.preventDefault();
}
render() {
return (
<div className='UserCard'>
<div className='UserCardTop'>
<form className='Submit' onSubmit={this.handleSubmit}>
<input
type="text"
name="names"
value={this.state.names}
ref={this.input}
onChange={this.handleChange} />
<input type="submit" value="Submit" />
</form>
<h3>{this.props.name} {this.props.last}</h3>
<div className='ImageContainer'>
<img alt="image" width="80" src={this.props.image} />
</div>
</div>
<div className='UserCardBottom'>
<h5>{this.props.email}</h5>
<h5>{this.props.cell}</h5>
<h5>{this.props.city}, {this.props.state}</h5>
</div>
</div>
)
}
}
export default User
App.js
import React, { Component } from "react";
import axios from "axios";
import User from './User'
import Filter from './Filter.js'
class App extends Component {
constructor(props) {
super(props);
this.state = {
users: [],
searchTerm: '',
alphabetical: 'az'
};
this.handleChange = this.handleChange.bind(this);
this.handleFilter = this.handleFilter.bind(this);
}
componentDidMount() {
axios.get("https://randomuser.me/api/?page=3&results=10&seed=abc")
.then(response => {
console.log(response.data.results);
this.setState({ users: response.data.results });
})
.catch(error => {
console.log(error);
});
}
handleFilter(filterInput) {
this.setState(filterInput)
}
handleChange(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
render() {
let sortedUsers;
if (this.state.alphabetical === "az") {
console.log("sorted");
sortedUsers = this.state.users.sort((a, b) =>
a.name.first > b.name.first ? 1 : -1
);
}
let filteredUsers = sortedUsers;
if (this.state.searchTerm)
filteredUsers = this.state.users.filter(u =>
u.name.first.startsWith(this.state.searchTerm) || u.name.last.startsWith(this.state.searchTerm)
);
const userNames = filteredUsers.map(u => {
return <User
key={u.email}
name={u.name.first}
last={u.name.last}
image={u.picture.large}
email={u.email}
city={u.location.city}
state={u.location.state}
cell={u.cell}
/>;
});
return (
<div>
<Filter
searchTerm={this.state.searchTerm}
onFilter={this.handleFilter}
></Filter>
<select
name="alphabetical"
value={this.state.alphabetical}
onChange={this.handleChange}>
<option value="az">
A to Z
</option>
<option value="za">Z to A</option>
</select>
{userNames}
</div>
);
}
}
export default App
A simple solution would be to add an onChangeFirst callback prop to your User component, which would be invoked with the new first name when handleSubmit() is called:
User.js
handleSubmit(event) {
event.preventDefault();
if(this.props.onChangeFirst) {
/* Pass this users state (with names data) to onChange callback */
this.props.onChangeFirst(this.state.names);
}
}
The onChangeFirst callback prop would be "wired up" to the App component so that when it is called (from inside User.js), the corresponding user object (in App.js) is updated with the newFirstName. You could add the onChangeUserFirstName() function as shown below, which updates the first field of the user object in the App components state:
App.js
/* Helper function that updates first name state for matching user */
const onChangeUserFirstName = (user, newFirstName) => {
/* Updates state with newly mapped users to new array, where first name
if updated to that supplied in changes.names for existing user match */
this.setState({ users : this.state.users.map(u => {
return (u === user) ? { ...u, first : newFirstName } : u;
});
});
}
const userNames = filteredUsers.map(u => {
/* Add (newFirstName) => onChangeUserFirstName(u, newFirstName) */
return <User
onChangeFirst={ (newFirstName) => onChangeUserFirstName(u, newFirstName) }
key={u.email}
name={u.name.first}
last={u.name.last}
image={u.picture.large}
email={u.email}
city={u.location.city}
state={u.location.state}
cell={u.cell}
/>;
});
I need to store the distance value in state. It should equal the distance passed as props + the distance selected by user. How to do this?
class Distance extends React.Component {
constructor(props) {
super(props);
this.state = {
distance: 0
};
}
onChange = e => {
}
render() {
return (
<div>
<p>{this.props.distance}</p>
<select onChange={this.onChange}>
<option>30km</option>
<option>50km</option>
<option>70km</option>
</select>
</div>
);
}
}
Using functional components, you can do this:
const Distance = () => {
const [distance, setDistance] = useState("");
return (
<div>
<p>{distance}</p>
<select onChange={(e) => setDistance({distance: e.target.value})}>
<option value="30">30km</option>
<option value="50">50km</option>
<option value="70">70km</option>
</select>
</div>
);
};
export default Distance;
In a case where you have multiple inputs, and only distance is a select input, you can do this to update distance while maintaining the values of other inputs:
const Distance = () => {
const [input, setInput] = useState({
distance: "",
time: "",
place: "",
});
return (
<div>
<p>{distance}</p>
<select onChange={(e) =>
setInput({ ...input, distance: e.target.value }}
>
<option value="30">30km</option>
<option value="50">50km</option>
<option value="70">70km</option>
</select>
</div>
);
};
export default Distance;
First add value attributes to your <option> elements, and then access the use the value of the <select> via e.currentTarget.value in your onChange handler like so:
class Distance extends React.Component {
constructor(props) {
super(props);
this.state = {
distance: 0
};
}
onChange = e => {
// Extract value of select like so. Use parseInt for
// improved type safety
const valueSelectedByUser = parseInt(e.target.value);
// Update distance in state via setState()
this.setState({ distance : this.props.distance + valueSelectedByUser });
}
render() {
return (
<div>
<p>{this.props.distance}</p>
<select onChange={this.onChange}>
<option value="30">30km</option>
<option value="50">50km</option>
<option value="70">70km</option>
</select>
</div>
);
}
}
You should include value for select and handle onChange event:
class Distance extends React.Component {
constructor(props) {
super(props);
this.state = {
distance: 0
};
}
onChange = e => {
this.setState({
distance: this.props.distance ? this.props.distance + e.target.value : e.target.value
});
}
render() {
return (
<div>
<p>{this.props.distance}</p>
<select onChange={this.onChange}>
<option value="30">30km</option>
<option value="50">50km</option>
<option value="70">70km</option>
</select>
</div>
);
}
}
you can simply do this like this, I have converted your code to functional components and also modified it, try this.
const Distance = () => {
const [distance, setDistance] = useState("");
return (
<div>
<p>{distance}</p>
<select onChange={(e) => setDistance(e.target.value)}>
<option value="30">30km</option>
<option value="50">50km</option>
<option value="70">70km</option>
</select>
</div>
);
};
export default Distance;