I'm trying to create a way to attach files from Reactjs Dropzone plugin to an axios POST request.
Currently, my module is doing the following ajax request:
submitPost() {
const formData = new FormData;
const err = this.validate();
if( !err ) {
this.setState({buttonText: 'Posting...'});
axios.post('/user/post/create/', {
content: this.state.post_content,
images: this.state.images,
headers: {
'Content-Type': 'multipart/form-data'
},
})
.then(response => {
console.log(response);
this.setState({buttonText: 'Success'});
setTimeout(
function() {
this.setState({
buttonText: 'Post',
post_content: '',
images: []
});
$('#post_content').val('');
}.bind(this), 1000
);
}).catch(error => {
console.log(error.response);
this.setState({buttonText: 'Error'});
setTimeout(
function() {
this.setState({buttonText: 'Post'});
}.bind(this), 1000
);
});
} else {
this.setState({buttonText: 'Error'});
setTimeout(
function() {
this.setState({buttonText: 'Post'});
}.bind(this), 1000
);
}
}
And the following states are defined:
constructor(props){
super(props);
this.state= {
progressValue: '0',
progressText: '0%',
buttonText: 'Post',
post_content: '',
images: []
}
}
And here is the Uploader Module i've written using Reactjs Dropzone:
import React, { Component } from 'react';
import Dropzone from 'react-dropzone'
import $ from "jquery";
export class Uploader extends Component {
constructor(props){
super(props);
this.state= {
images: this.props.images
}
}
onDrop(files) {
this.setState({
images: files
});
console.log(files);
this.props.handleImageUpload(files);
}
render() {
return (
<div className="uploader">
<div className="previews">
{this.state.images.map((file) =>
<div
className="preview"
key={file.preview}>
<img src={file.preview} />
</div>
)}
</div>
<Dropzone onDrop={this.onDrop.bind(this)}>
<p>Try dropping some files here, or click to select files to upload.</p>
</Dropzone>
</div>
);
}
}
Any help would be appreciated, I'm currently trying to upload the files from the Images state which comes through as an array, but comes through in this format:
[{"preview":"blob:http://outist.local/3c3fc96b-b89d-41c8-8835-3309be8ac430"},{"preview":"blob:http://outist.local/6cf9aa40-0538-4cef-affe-58951afef2eb"},{"preview":"blob:http://outist.local/4631977b-1301-498d-b4e8-611f9a57b6bb"},{"preview":"blob:http://outist.local/1650a49c-2eed-408c-a035-473cade2bfa6"}]
Related
I am trying to get a new fortune to get included into my array when someone submits a fortune but I can't get it to work now matter what im trying. Do I like it to the other file where someones submit their fortune, or am I messing up somewhere else?
import React from "react";
import {Link} from "react-router-dom"
import AddFortune from "./add-fortune";
class Fortune extends React.Component {
constructor(props) {
super(props);
this.state = {
fortunes: [
"An exciting opporunity lies ahead",
"A long time friend will brirng wise advice in the coming week",
"You will find great fortunes in unexpected places",
"Never give up... Unless you want to thats cool too",
"111",
"222",
"333",
"444",
"Maybe a nap is what you need",
"Don't Text Your EX!"
],
array.push('
fortune: "" ');
array.splice(array.length, 0, '{fortune:""}');
array[array.length] = fortune: "";
}
}
componentDidMount() {
this.getFortune();
}
getFortune = () => {
let rand = Math.floor(Math.random() * (this.state.fortunes.length) + 0)
console.log(rand);
this.setState({
fortune: this.state.fortunes[rand]
})
}
render() {
return (
<body>
<div className="home-buttons-wrapper">
<button onClick={this.getFortune}>Your Fortune</button>
</div>
<h5>{this.state.fortune}</h5>
</body>
)
}
}
console.log('getFortune');
export default Fortune;
What im trying to get to be added to the fortunes file
import React, { Component } from 'react'
export default class AddFortune extends Component {
constructor(props) {
super(props)
this.state = {
nameInput: "",
loading: false,
error: false
}
this.handleChange = this.handleChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
}
handleChange(event) {
this.setState({ [event.target.name]: event.target.value })
}
handleSubmit(event) {
event.preventDefault()
this.setState({
loading: true,
error: false
})
fetch("https://backend-edwin.herokuapp.com/item/add", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
name: this.state.nameInput
})
})
.then(response => response.json())
.then(data => {
if (data.id) {
this.props.history.push("/fortune")
}
})
.catch(error => {
console.log("Error adding fortune ", error)
this.setState({
loading: false,
error: true
})
})
}
render() {
return (
<div className='add-item-wrapper'>
<h2>Add Fortune</h2>
<form onSubmit={this.handleSubmit}>
<input
type="text"
placeholder="fortune"
name="nameInput"
value={this.state.nameInput}
onChange={this.handleChange}
/>
<button type="submit" disabled={this.state.loading}>Add Fortune</button>
</form>
{this.state.loading ? <div className="loading">Submitting...</div> : null}
{this.state.error ? <div className="error">An error occured... Please try again later.</div> : null}
</div>
)
}
}
Here is a method to get a random fortune from a list of fortunes.
import React from "react";
class Fortune extends React.Component {
constructor(props) {
super(props);
this.state = {
fortunes: [],
fortune: '',
loading: true,
error: false
}
}
componentDidMount() {
fetch("https://backend-edwin.herokuapp.com/item/", {
method: "GET",
headers: { "content-type": "application/json" },
})
.then(response => response.json())
.then(data => {
this.setState({
loading: false,
fortunes: data, //check how the data is coming from api and add the variable here if fortunes list `if data.fortunes` then add data.fortunes here
error: false
}, this.getFortune)
})
.catch(error => {
console.log("Error fetching fortune ", error)
this.setState({
loading: false,
error: true
})
})
}
getFortune = () => {
let rand = Math.floor(Math.random() * (this.state.fortunes.length - 1) + 0)
console.log(rand);
this.setState({
fortune: this.state.fortunes[rand]
})
}
render() {
if(this.state.loading) {
return (<div>Loading .....</div>)
}
if(this.state.error) {
return (<div>Error occurred in API</div>)
}
return (
<div>
<div className="home-buttons-wrapper">
<button onClick={this.getFortune}>Your Fortune</button>
</div>
<h5>{this.state.fortune}</h5>
</div>
)
}
}
export default Fortune
i try fetch array data from a API with token, the problem is i fail to render/bind to display,every time debug will show error message like this. Please guide me, im new to react, this is my 1st app.
how to bind array to myadapater?
error
here my code:
import React, { Component } from "react";
import ReactDOM from "react-dom";
const url = " "; //api customer
const token = " "; //token
class Client extends Component {
constructor(props) {
super(props);
this.state = {
error: undefined,
isLoaded: false,
items: []
};
this.getData = this.getData.bind(this);
}
componentDidMount() {
this.getData();
}
getData() {
return fetch(url, {
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization: "Bearer " + token
}
})
.then((res) => res.json())
.then(
(result) => {
this.setState({
isLoaded: true,
items: result
});
},
(error) => {
this.setState({
isLoaded: true,
error
});
}
);
}
render() {
const { error, isLoaded, items } = this.state;
if (error) {
return <div>Error: {error.message}</div>;
} else if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<div>
<p>data {items}</p>
{items.map((items) => (
<div>{items.name}</div>
))}
</div>
);
}
}
}
export default Client;
There is only one real issue.
The use of {items} in the render method. If you want to display the actual JSON try {JSON.stringify(items)} instead.
Besides that i would also not use the same name in the map. So instead of items for the map function i would use item since you are dealing with one of the items.
<div>
<p>data {JSON.stringify(items)}</p>
{items.map((item) => (
<div>{item.name}</div>
))}
</div>
Additionally, since you only use getData in the componentDidMount you do not need to bind it in the constructor (that is required if you intent to pass that function to other component/functions outside of the current one)
And you also do not need to return anything for the getData function since you handle the result in the then handlers.
So,
class Client extends Component {
constructor(props) {
super(props);
this.state = {
error: undefined,
isLoaded: false,
items: []
};
}
componentDidMount() {
this.getData();
}
getData() {
fetch(url, {
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization: "Bearer " + token
}
})
.then((res) => res.json())
.then(
(result) => {
this.setState({
isLoaded: true,
items: result
});
},
(error) => {
this.setState({
isLoaded: true,
error
});
}
);
}
render() {
const { error, isLoaded, items } = this.state;
if (error) {
return <div>Error: {error.message}</div>;
} else if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<div>
<p>data {JSON.stringify(items)}</p>
{items.map((item) => (
<div>{item.name}</div>
))}
</div>
);
}
}
}
I am trying to call two different functions to display data on my page and one is working (getUserscards) and the second one is not (getUserInfo). I saw that you can put two different function calls for the data in componentDidMount and I have tried doing it several ways but the data for the email and names is not showing up. I will include the code from my profilepage where the componentDidMount is and from my api page where the function is made.
Here is my code in profilepage. js:
import React from 'react'
import { getUsersCards, getUsersInfo } from '../Api'
class ProfilePage extends React.Component {
constructor () {
super()
this.state = {
token: window.localStorage.getItem('login_auth_token'),
username: localStorage.getItem('login_username') || '',
email: '',
first_name: '',
last_name: '',
cards: []
}
}
componentDidMount () {
if (this.state.token) {
getUsersCards(this.state.token)
.then(cards => this.setState({ cards: cards }))
}
getUsersInfo(this.state.email, this.state.first_name, this.state.last_name)
.then(data => this.setState({ data: data }))
}
componentDidUpdate (prevProps, prevState) {
if (this.state.token && this.state.token !== prevState.token) {
getUsersCards(this.state.token).then(cards => this.setState({ cards: cards }))
}
}
render () {
return (
<div>
<div className='container2'>
<div>
<p>Username: {this.state.username}</p>
</div>
<div>
Email: {this.state.email}
</div>
<div>
<p>Name: {this.state.first_name}{this.state.last_name}</p>
</div>
</div>
<div>
{this.state.cards.map(card => <p className='container' key={card.id}> Title: {card.card_name} <br /> Card: {card.card_text}</p>)}
</div>
</div>
)
}
}
export default ProfilePage
And here is the function from my api.js page:
export function getUsersInfo (token) {
return request.get('/users/info', {
headers: {
Authorization: `Token ${token}`
}
}).then(res => {
console.log(res.data)
return res.data
})
}
The thing is, when you call this.setState({ data: data }), in your state MUST HAVE a key data.
Maybe change into this may help
this.setState({ email: data.email, first_name: data.first_name, last_name: data.last_name })
Just need the exactly key to work
the problem is likely here,
export function getUsersInfo (token) {
return request.get('/users/info', {
headers: {
Authorization: `Token ${token}`
}
}).then(res => {
console.log(res.data)
return res.data //!! note
})
}
You are returning raw data from the server when are you parsing it to json, YOu Must parse it somehow to make is object so you can use.
I have two components, Client and App, and a fetch function. App is the child component of Client. I want to update Client's state using the return value from the method App calls. However, Client's state response is undefined after the fetch. I'm not sure why this code does not work.
import React, { Component } from 'react';
import './App.css';
function post(user, token, data){
console.log('fetching...')
fetch(`/project`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Basic '+ btoa(user+':'+token),
},
body: JSON.stringify(data)
}).then(r => {
if (!r.ok)
throw Error(r.status);
r.json().then(r => {return(r)});
}).catch(error => {throw Error(error)})
}
class Client extends Component {
constructor(props) {
super(props);
this.state = {
user: '',
token: '111',
project: {'project':'demo'},
response: {},
};
this.updateState = this.updateState.bind(this);
};
updateState(){
const { user, token, project } = this.state;
post(user, token, project).then(text => this.setState({ response: text
}));
}
render() {
return (
<App updateState={this.updateState}/>
)
}
}
class App extends Component {
render() {
return (
<div className="App">
<button onClick={ () => {
this.props.updateState()} }>Fetch Project</button>
</div>
);
}
}
EDIT: I changed my post() to this and it works :)
async function post(user, token, data){
console.log('fetching...')
const response = await fetch(`/project`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Basic '+ btoa(user+':'+token),
},
body: JSON.stringify(data)
}).catch(error => {throw Error(error)});
if(!response.ok)
throw Error(response.status);
const obj = await response.json();
return(obj);
}
If you are working with promises, you can do something like this.
import React, { Component } from "react";
async function post() {
// fetch //
return await fetch("https://hipsum.co/api/?type=hipster-centric");
}
class Client extends Component {
constructor(props) {
super(props);
this.state = {
response: "12"
};
this.updateState = this.updateState.bind(this);
}
async updateState(res) {
const text = await res().then(res => res.text());
this.setState({ response: text });
}
render() {
return (
<>
{this.state.response}
<App updateState={this.updateState} />
</>
);
}
}
class App extends Component {
render() {
return (
<div>
<button
onClick={() => {
this.props.updateState(post);
}}
>
Fetch
</button>
</div>
);
}
}
export default Client;
sandbox
It will be nice to know all the code for the fetch function but I think the problem is mostly here:
this.props.updateState(post())
That call is synchronous and the fetching process isn't. You need a better approach with await or promises or a callback.
I am trying to bring up a dashboard page with a react table. I want table to be refreshed every 2 seconds.Also I have two fetch api calls , where result of the first one is passed as a parameter to the second. Also second fetch call must set the chart data every two seconds.
Also if there are multiple tables that follows the same implementation of such fetch calls, how can I do it?
What is the better way to do it?
Help would be appreciated
import * as React from 'react';
import ReactTable from 'react-table';
import 'react-table/react-table.css';
interface IState {
data: any[];
}
export default class Dashboard extends React.Component<{},IState> {
constructor(props: any) {
super(props);
this.state = {
data: [],
}
componentDidMount()
{
const url="/api/query/fetch";
var result = fetch(url, {
method: 'post',
body : JSON.stringify({"id":"abc"),
headers: {
'Content-Type': 'application/json'
},
}).then(function(response) {
return response.json();
}).then(function(data) {
return fetch('api/query/fetch' + data.id); // want this call to be under setInterval such that chart data refreshes every 2 seconds, s uch that table data refreshes every 2 seconds
})
.then(function(response) {
return response.json();
})
.catch(function(error) {
console.log('Request failed', error)
})
result.then(function(r) {
this.setState({data:r});
});
}
render(){
return(
<ReactTable
data={this.state.data}
columns={columns} //column config object
/>
)
}
}
import * as React from 'react';
import ReactTable from 'react-table';
import 'react-table/react-table.css';
interface IState {
data: any[];
id: any;
}
export default class Dashboard extends React.Component<{}, IState> {
constructor(props: any) {
super(props);
this.state = {
data: [],
id: null
}
}
componentDidMount() {
const url = "/api/query/fetch";
fetch(
url,
{
method: 'post',
body: JSON.stringify({ "id": "abc"}),
headers: {
'Content-Type': 'application/json'
}
}
).then(function (response) {
return response.json();
}).then(function (data) {
this.setState({
id: data.id
}, () => this.fetchData())
});
}
fetchData() {
fetch('api/query/fetch' + this.state.id)
.then(function (response) {
return response.json();
})
.then(function (r) {
this.setState({ data: r });
setTimeout(() => {
this.fetchData();
}, 2000);
})
.catch(function (error) {
console.log('Request failed', error)
})
}
render(){
return (
<ReactTable
data={this.state.data}
columns={columns} //column config object
/>
)
}
}