Reputation: 4296
I am struggling with a situation where I need to grab the value of an input field to make an API call.
So What I have is this:
import React, { Component } from 'react'
import axios from 'axios';
const fetchWeather = function (e) {
e.preventDefault();
axios.get('https://api.openweathermap.org/data/2.5/weather?q=Zeist&appid=MYID')
.then(res => {
console.log(res.data);
});
console.log();
}
export default class App extends Component {
render() {
return (
<div>
<form onSubmit = {fetchWeather}>
<input type = 'text' placeholder = 'Your city' ref="city"></input>
<input type = 'submit' placeholder='Submit' value = 'Submit'></input>
</form>
</div>
);
}
}
A form that runs a function on submit, I used preventDefault
to stop the page from loading.
The function runs and the page doesn't reload. Now I'd like to grab the text from the input field and log it in that function. The reason why I want this is so I can use it in my API call as a query parameter. I tried many things. I tried logging e
to see what is inside. It's a very big object and I couldn't find the value I'm looking for. I tried using ref
, this didn't work either. Any idea how I could solve this issue?
Upvotes: 0
Views: 12688
Reputation: 725
You can use a controlled component: https://reactjs.org/docs/forms.html.
I simulated the fetch operation in the snippet.
const fetchWeather = function (data) {
// simulating fetch
setTimeout(function() {
console.log('GETTING DATA ' + JSON.stringify(data))
}, 500)
}
// Controlled Component: https://reactjs.org/docs/forms.html
class App extends React.PureComponent {
constructor(props) {
super(props)
this.state = {
city: ''
}
this._handleInputChange = this._handleInputChange.bind(this)
this._handleSubmit = this._handleSubmit.bind(this)
}
_handleInputChange (event) {
const { value, name } = event.target
this.setState({
[name]: value
})
}
_handleSubmit (event) {
event.preventDefault()
fetchWeather(this.state)
}
render() {
const { city } = this.state
return (
<div>
<form onSubmit={this._handleSubmit}>
<input
type='text'
name='city'
placeholder='Your city'
value={city}
onChange={this._handleInputChange}
/>
<input type='submit' placeholder='Submit' value='Submit' />
</form>
</div>
)
}
}
ReactDOM.render(
<App />,
document.getElementById('react')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="react"></div>
Upvotes: 1
Reputation: 20755
You are using Uncontrolled Components.
You need to move your fetchWeather
function inside of your component,
export default class App extends Component {
fetchWeather = (e) => {
e.preventDefault();
console.log(this.refs.city.value)//You will get vlue here
axios.get('https://api.openweathermap.org/data/2.5/weather?q=Zeist&appid=MYID')
.then(res => {
console.log(res.data);
});
console.log();
}
render() {
return (
<div>
<form onSubmit = {this.fetchWeather}> //refer your function using `this`
<input type = 'text' placeholder = 'Your city' ref="city"></input>
<input type = 'submit' placeholder='Submit' value = 'Submit'></input>
</form>
</div>
);
}
}
Better way is, using state
. This is called Controlled Components.
export default class App extends Component {
state={
city: ''
}
handleChange = (e) => {
this.setState({[e.target.name]:e.target.value})
}
fetchWeather = (e) => {
e.preventDefault();
console.log(this.state.city)//You will get vlue here
axios.get('https://api.openweathermap.org/data/2.5/weather?q=Zeist&appid=MYID')
.then(res => {
console.log(res.data);
});
console.log();
}
render() {
return (
<div>
<form onSubmit = {this.fetchWeather}> //refer your function using `this`
<input type = 'text' placeholder = 'Your city' name="city" value={this.state.city} onChange={this.handleChange} ></input>
<input type = 'submit' placeholder='Submit' value = 'Submit'></input>
</form>
</div>
);
}
}
Upvotes: 3