how to fetch and display API content Onsubmit - reactjs

I am developing a weather forecast app using Reactjs but i'm having a hard time Fetching/displaying API data
I know this question might have a duplicate but i have looked up all related problems/solutions on this platform and elsewhere but none solved my problem
//const API;
class WeatherApp extends React.Component{
constructor(props){
super(props);
this.state = {
location: "",
reports:[]
}
}
//functions should be written outside the constructor method
onSubmit = event => {
//prevents default loading of the page when this function "onSubmit"
//is called
event.preventDefault();
//saving the value of the textbox to a variable/const
if(this.searchbox.value !== ""){
const searchResult = this.searchbox.value;
//update the state object
this.setState({
location: searchResult + " weather report"
});
}else{
alert("please ensure that field is not empty!");
return;
}
};
componentDidMount(){
if(this.searchbox.value !== ""){
fetch(`api.openweathermap.org/data/2.5/forecast?q=london,uk ${/*this.searchbox.value +*/ KEY}`,{
method: "GET",
dataType: "JSON",
headers: {
"Content-Type": "application/json; charset=utf-8",
}
})
.then(response => { response.json() })
.then(data => {
console.log(data);
this.setState({ reports: data.list})
});
}
}
render(){
return(
<div className="weather-app">
<WeatherAppHeader />
<div className="weather-body">
<div className="entry-pane">
<form onSubmit ={this.onSubmit} >
<input
type="text"
id="search-box"
placeholder="Location e.g Abuja, NG"
size="40"
ref={input => this.searchbox = input} />
<button type="submit" id="search-btn">search</button>
</form>
</div>
<SearchedLocation location={this.state.location} />
<WeatherReport reports={this.state.reports} />
</div>
</div>
);
}
}
const WeatherAppHeader = () => (
<nav> WEATHER FORECAST </nav>
);
const SearchedLocation = ({location}) => (
<div className="searched-loc">{location}</div>
);
SearchedLocation.propTypes = {
location: PropTypes.string
}
///Declaring state within the WeatherReport component
const WeatherReport = ({reports}) => (
<div className="weather-report" >
<ul className="report-list">
{reports.map(report => (
<li key={report.id} className="daily-report">
<span className="daily-report-day">{report.day}</span><br/>
<span className="daily-report-icon">{report.icon}</span><br/>
<span className="daily-report-temp">{report.main.temp}</span>
</li>
))}
</ul>
</div>
);
WeatherReport.propTypes = {
report: PropTypes.array
}
ReactDOM.render(<WeatherApp />, document.getElementById('root'));
i want to display all data from the API on the browser console when the form is submitted but to no avail...and theres no error message. pls can anyone help?

After your fetch call, you are not correctly returning the response when you do .then(response => { response.json() }). Just remove the curly-braces, that way you do an implicit return. Otherwise, if you use curly-braces you must explicitly write .then(response => { return response.json() })
Working code:
componentDidMount(){
if(this.searchbox.value !== ""){
fetch(`api.openweathermap.org/data/2.5/forecast?q=london,uk ${/*this.searchbox.value +*/ KEY}`,{
method: "GET",
dataType: "JSON",
headers: {
"Content-Type": "application/json; charset=utf-8",
}
})
.then(response => response.json())
.then(data => {
console.log(data);
this.setState({ reports: data.list})
});
}
}

Related

Can't send files using Redux Form

I'm creating a webpage for me and I'm working with Redux/Redux Form. My backend is working fine, but I can't figure out how to work on my front-end. I'm not using any library to fetch the image in my front, I just copy and pasted a FieldFileInput and it's working fine.
Here is my PostForm.tsx:
renderInput = ({input, label, meta}: {input: any, label: any, meta: any}) => {
const className = `field ${meta.error && meta.touched} ? 'error' : ''`;
return (
<div className={className}>
<label>{label}</label>
<div className="input-group input-group-lg">
<input className="form-control"{...input} autoComplete="off"/>
</div>
{this.renderError(meta)}
</div>
)
};
onSubmit = (formValues: any) => {
//#ts-ignore
this.props.onSubmit(formValues)
};
render() {
return (
<form
onSubmit={ this.props.handleSubmit(this.onSubmit)}
className="ui form error"
>
<div className="create-post-field-two">
<Field
name="title"
component={this.renderInput}
label="Enter Title"
/>
</div>
<div className="create-post-field-two">
<Field
name="body"
component={this.renderInput}
label="Enter Description"
/>
</div>
<div className="create-post-field-two">
<Field
name="imageUrl"
component={FieldFileInput}
label="Enter Image"
/>
</div>
<div className="postButton">
<button className="btn btn-outline-secondary">Submit</button>
</div>
</form>
)
}
}
In this page I'm certain that everything works correctly, because I receive all data in my Action.
Here is my Redux Action
export const createPost = ( formValues: any) => async(dispatch: any, getState: any) => {
const { userId } = getState().auth;
let token = userId
const headers = {
// 'Content-Type': 'multipart/form-data',
authorization: `Bearer ${token}`,
};
let formData = new FormData();
formData.append('imageUrl', formValues.imageUrl);
try {
const response = await AlleSys.post('/posts', {...formValues, image: formData}, {headers})
dispatch({type: CREATE_POST, payload: response.data})
history.push('/')
}catch (err) {
console.log("ERROR: Couldn't post for identified user");
}
};
If I uncomment the Content-Type I receive the error Error: Multipart: Boundary not found
in my Back-End.
Here Is a screenshot of my request using insomnia.
I'm stuck on this for days and I can't figure out how to achieve the file upload in the front-end. Please don't mind the typings, I'll correct later.
I used bodyFormData.append to my form fields in the Redux Action and worked like a charm.
export const createPost = ( formValues: any) => async(dispatch: any, getState: any) => {
const { userId } = getState().auth;
let token = userId
const headers = {
authorization: `Bearer ${token}`,
Accept: 'application/json',
};
const { title, body, image } = formValues;
const bodyFormData = new FormData();
bodyFormData.append('title', title);
bodyFormData.append('body', body);
bodyFormData.append('image', image);
try {
const response = await AlleSys.post('/posts', bodyFormData, {headers})
console.log(response)
dispatch({type: CREATE_POST, payload: response.data})
history.push('/')

Rect Post request

I am creating project in React /Django Rest Framework and I want to send Post request. My problem is that I am always sending string and I should send list of int.
My component look like this
const NewLecture = (props) => {
const[ lecture, setLecture] = useState({
title:'',
programs: [],
})
const dispatch = useDispatch()
const history = useHistory()
// console.log('this is history:', history)
const program_id = props.match.params.id;
//event handlers
const newLectureHandler = (event) => {
const{name, value}= event.target
setLecture({
...lecture,
[name]:value
})
};
useEffect(() => {
console.log('mounting in NewLecture');
dispatch(LecturesActions())
dispatch(GetPrograms())
}, [])
const handleSubmit = e =>{
e.preventDefault()
props.close()
dispatch(sendLecture(lecture, program_id, history))
}
const stringtoArray = (arg)=> {
console.log('this is arg', [arg]);
return [arg]
}
return (
<NewGradeStyled>
<div className="new-grade-style">
<h1>Create New Lecture</h1>
<form >
<div className="form-grade">
<label htmlFor="title">Lecture Name</label>
<input type="text" name="title" onChange={newLectureHandler}/>
</div>
<div className="form-grade">
<label htmlFor="programs">Program</label>
{/* <input type="number" name="programs" onChange={newLectureHandler}/> */}
<select name="programs" onChange={newLectureHandler}>
<option > </option>
{props.data ? <option value={props.data.id}>{props.data.name}</option> : ''}
</select>
</div>
<div className="btn-group">
<button className="save" onClick={handleSubmit}>Save</button>
<button onClick={props.close}>Cancle</button>
</div>
</form>
</div>
</NewGradeStyled>
)
}
export default withRouter(NewLecture)
and this is my action
export const sendLecture = (lecture) => (dispatch, getState) => {
const{title, programs} = lecture
const token = getState().token
const config = {
body: JSON.stringify(lecture),
method: "POST",
headers: new Headers({
"Content-Type": "application/json",
"Authorization": `Bearer ${token}`
}),
body: JSON.stringify({title, programs})
};
fetch(`${baseUrl}/backend/api/lectures/new/`, config)
.then((res) => res.json())
.then((data)=>{
console.log('Post lecture action', data)
dispatch({type: 'GET_LECTURE_DATA', payload: data})
});
}
I expect to get this from JSON
{
"title":"some string"
"programs":[1]
}
reducer
const initialState = {
lecture_data:[],
}
export const authReducer = (state = initialState, action) => {
switch (action.type) {
case "GET_LECTURE_DATA": {
const lecture_data = action.payload;
return { ...state, lecture_data };
}
default:
return state;
}
}
If I send it as input type= "number" result is always the same I get error "Expected a list of items but got type "str"."
I donĀ“t kow how I should change it. Do you have any Ideas?
In this part:
const config = {
body: JSON.stringify(lecture),
method: "POST",
headers: new Headers({
"Content-Type": "application/json",
"Authorization": `Bearer ${token}`
}),
body: JSON.stringify({ title, programs })
};
you set the body property twice. Is that intentional?
You write the api expects a list. Did you mean to pass this body: JSON.stringify( [title, programs ]) Although that would send an array of objects of which the first item is title, and the second is programs. Can you clarify what the API expects? And what the structure of title and programs looks like?

displaying Flash message in react

My task is to display flash message("successfully created") on clicking the submit button.[On clicking the submit button , data will be stored in the server]I have run this command npm i react-flash-message.
<form onSubmit={this.handleSubmit}>
<input type="submit" value="Submit" />
</form>
handleSubmit function:
handleSubmit(event) {
fetch('url', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: this.state.name,
description: this.state.description
})
}).then(res => {
return res.json()
})
.then(data => console.log(data))
.then(() => {
window.location.reload(false)
/* return (
<div>
<FlashMessage duration={5000}>
<strong>I will disapper in 5 seconds!</strong>
</FlashMessage>
</div>
) */
})
/* window.flash('record has been created successfully!', 'success') */
.catch(error => console.log('ERROR from create component'))
}
}
I have commented the code I have tried to display flash message. But it is not working. Please someone help me to display the flash message.
According to react-flash-message page , you should include the FlashMessage in your render. So you may need to have a flag variable to set as true when you want to show the FlashMessage
Example:
in your render :
<form onSubmit={this.handleSubmit}>
<input type="submit" value="Submit" />
{ this.state.showMessage &&
<div>
<FlashMessage duration={5000}>
<strong>I will disappear in 5 seconds!</strong>
</FlashMessage>
</div>
}
</form>
handleSubmit function :
handleSubmit(event) {
this.setState({ showMessage: false });
fetch('url', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: this.state.name,
description: this.state.description
})
}).then(res => {
return res.json()
})
.then(data => console.log(data))
.then(() => {
this.setState({ showMessage: true });
})
/* window.flash('record has been created successfully!', 'success') */
.catch(error => console.log('ERROR from create component'))
}
}
main function if you are using class:
constructor(props) {
super(props);
this.state = {
showMessage: false
};
}
https://www.npmjs.com/package/react-flash-message
Easy peasy..
Whenever using onSubmit, dont forget to use event.preventDefault()..
And try using only one then block.
Now maintain a state variable, to set the status of the result. Once the result is fetched set the result status to true.
Render your FlashMessage component, when its true.
https://codesandbox.io/s/lucid-taussig-9x0o3

How to clear the input after posting the data through fetch and making the code execute successful

I'm new to react, have created a chat using reactjs. I'm using "POST" request through fetch to post new message for a particular conversation. My Objective is when i send a message, then it should clear the input but unable to clear the input after sending message. Need to write for error also.. Anyone can help me in this?
myCode:
handleChange = event => {
this.setState({ [event.target.name]: event.target.value });
};
handleSend = event => {
const { phonNo } = this.props.phonNo;
event.preventDefault();
console.log("phone : " + "+" + phonNo);
this.setState({ toPhoneno: phonNo });
console.log("phonefkjdk : " + "+" + this.state.toPhoneno);
const data = {
toPhoneno: "+" + this.state.toPhoneno,
body: this.state.body
};
fetch("/api/messages", {
method: "POST",
body: JSON.stringify(data),
headers: { "Content-Type": "application/json" }
})
.then(res => res.json())
.then(() => {});
};
render () {
return (
<div>
<input
className="sendMessage"
onChange={this.handleChange}
/>
<Button onClick={this.handleSend} className="sendBtn" icon>
<Icon name="send" color="blue" />
</Button>
</div>
);
}
Can anyone help me in this ? Thanks in advance
You can clear it end of the fetch Promise chain.
fetch("/api/messages", {
method: "POST",
body: JSON.stringify(data),
headers: { "Content-Type": "application/json" }
})
.then(res => res.json())
.then(() => {
this.setState({ sendMessage: "" })
});
input should be controlled and it should have a name.
render () {
return (
<div>
<input
className="sendMessage"
name="sendMessage"
value={this.state.sendMessage}
onChange={this.handleChange}
/>
<Button onClick={this.handleSend} className="sendBtn" icon>
<Icon name="send" color="blue" />
</Button>
</div>
);
}

React API returns empty

fairly new to react but I have the following API data I want to create as a list or whatever:
https://jsonblob.com/53c7f296-d79d-11e8-839a-a312b719c60a
My react component looks like this:
class Contacts extends Component {
constructor(props) {
super(props)
this.state = {
contacts:[]
}
}
componentDidMount() {
fetch('https://api.billysbilling.com/v2/contacts?organizationId=kZeGqbBRSXyeeDoWNkF3jQ',{
headers: {
'X-Access-Token': API_KEY,
'Content-Type': 'application/json'
},
})
.then(response => {
return response.json();
})
.then(response => console.log(response))
.then(d => {
this.setState({ contacts: d });
console.log("state", this.state.contacts)
})
}
render() {
return (
<div>
{
this.state.contacts.map(((contact, index) =>
<th key={`${contact.contact}${index}`}>
<div>
<div>
{contact.contact}
</div>
</div>
</th>
))
}
</div>
);
}
But however it seems to return nothing.
The console.log actually shows the data, so I am pretty stuck.
It would be awesome if some of you could help.
The state also just returns an empty array in the react tools in chrome.
When you write then(response => console.log(response)), you are not returning anything, so d will be undefined in the function given to the following then.
You could write it like this instead:
fetch('https://api.billysbilling.com/v2/contacts?organizationId=kZeGqbBRSXyeeDoWNkF3jQ',{
headers: {
'X-Access-Token': API_KEY,
'Content-Type': 'application/json'
},
})
.then(response => {
return response.json();
})
.then(d => {
console.log(d);
this.setState({ contacts: d.contacts });
});

Resources