Class properties must be methods. Expected '(' but instead saw '=' - javascript

I have a react app, and I have this code, but it looks like the fetchdata m ethod is full of syntax errors, the first one shown on the title of the question.
Whats wrong with the method?
import React, { Component } from 'react';
import { Row, Col } from 'antd';
import PageHeader from '../../components/utility/pageHeader';
import Box from '../../components/utility/box';
import LayoutWrapper from '../../components/utility/layoutWrapper.js';
import ContentHolder from '../../components/utility/contentHolder';
import basicStyle from '../../settings/basicStyle';
import IntlMessages from '../../components/utility/intlMessages';
import { adalApiFetch } from '../../adalConfig';
const data = {
TenantId: this.this.state.tenantid,
TenanrUrl: this.state.tenanturl,
TenantPassword: this.state.tenantpassword
};
const options = {
method: 'post',
data: data,
config: {
headers: {
'Content-Type': 'multipart/form-data'
}
}
};
export default class extends Component {
constructor(props) {
super(props);
this.state = {value: ''};
this.handleChangeTenantUrl = this.handleChangeTenantUrl.bind(this);
this.handleChangeTenantPassword = this.handleChangeTenantPassword.bind(this);
this.handleChangeTenantId= this.handleChangeTenantId.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChangeTenantUrl(event){
this.setState({tenanturl: event.target.value});
}
handleChangeTenantPassword(event){
this.setState({tenantpassword: event.target.value});
}
handleChangeTenantId(event){
this.setState({tenantid: event.target.value});
}
handleSubmit(event){
alert('A name was submitted: ' + this.state.value);
event.preventDefault();
fetchData();
}
fetchData = () => {
adalApiFetch(fetch, "/tenant", options)
.then(response => response.json())
.then(responseJson => {
if (!this.isCancelled) {
this.setState({ data: responseJson });
}
})
.catch(error => {
console.error(error);
});
};
upload(e) {
let data = new FormData();
//Append files to form data
let files = e.target.files;
for (let i = 0; i < files.length; i++) {
data.append('files', files[i], files[i].name);
}
let d = {
method: 'post',
url: API_SERVER,
data: data,
config: {
headers: {
'Content-Type': 'multipart/form-data'
},
},
onUploadProgress: (eve) => {
let progress = utility.UploadProgress(eve);
if (progress == 100) {
console.log("Done");
} else {
console.log("Uploading...",progress);
}
},
};
let req = axios(d);
return new Promise((resolve)=>{
req.then((res)=>{
return resolve(res.data);
});
});
}
render(){
const { data } = this.state;
const { rowStyle, colStyle, gutter } = basicStyle;
return (
<div>
<LayoutWrapper>
<PageHeader>{<IntlMessages id="pageTitles.TenantAdministration" />}</PageHeader>
<Row style={rowStyle} gutter={gutter} justify="start">
<Col md={12} sm={12} xs={24} style={colStyle}>
<Box
title={<IntlMessages id="pageTitles.TenantAdministration" />}
subtitle={<IntlMessages id="pageTitles.TenantAdministration" />}
>
<ContentHolder>
<form onSubmit={this.handleSubmit}>
<label>
TenantId:
<input type="text" value={this.state.tenantid} onChange={this.handleChangeTenantId} />
</label>
<label>
TenantUrl:
<input type="text" value={this.state.tenanturl} onChange={this.handleChangeTenantUrl} />
</label>
<label>
TenantPassword:
<input type="text" value={this.state.tenantpassword} onChange={this.handleChangeTenantPassword} />
</label>
<label>
Certificate:
<input onChange = { e => this.upload(e) } type = "file" id = "files" ref = { file => this.fileUpload } />
</label>
<input type="submit" value="Submit" />
</form>
</ContentHolder>
</Box>
</Col>
</Row>
</LayoutWrapper>
</div>
);
}
}

You have written your fetchData method in the form of a class field which is not part of the language yet. You could add the Babel plugin proposal-class-properties or a preset that has it, like the stage 2 preset. (Note that the class field proposal is a finished stage 4 proposal as of April 2021.)
If you don't want to configure Babel, you could bind the method in your constructor instead, like you have done with your other methods:
export default class extends Component {
constructor(props) {
super(props);
this.state = {value: ''};
this.handleChangeTenantUrl = this.handleChangeTenantUrl.bind(this);
this.handleChangeTenantPassword = this.handleChangeTenantPassword.bind(this);
this.handleChangeTenantId= this.handleChangeTenantId.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.fetchData = this.fetchData.bind(this);
}
fetchData() {
adalApiFetch(fetch, "/tenant", options)
.then(response => response.json())
.then(responseJson => {
if (!this.isCancelled) {
this.setState({ data: responseJson });
}
})
.catch(error => {
console.error(error);
});
}
// ...
}

Have you defined the fetchdata variable previously?If not, perhaps you should do it in the current line:
var fetchdata = () => { ...

Related

upload image and text with form

I'm learning React with Strapi.
I made a form to add data to the database. I manage to send my img in the upload api and the text data in the Animals api, however, I can't manage to link the two. Ie to make sure that the image also goes on the animal that I add.
Thank you all for your future help.
import React from "react";
import { useForm } from "react-hook-form";
import axios from "axios";
import React from "react";
import { useForm } from "react-hook-form";
import axios from "axios";
class AddAnimal extends React.Component {
constructor(props) {
super(props);
this.state = {
modifiedData: {
nom: '',
description: '',
image : '',
races: [],
images :[],
},
allRaces: [],
error: null,
};
}
onImageChange = event => {
console.log(event.target.files);
this.setState({
images: event.target.files,
});
};
componentDidMount = async () => {
try {
const response = await axios.get('http://localhost:1337/api/races');
this.setState({ allRaces: response.data.data });
} catch (error) {
this.setState({ error });
}
};
handleInputChange = ({ target: { name, value } }) => {
this.setState(prev => ({
...prev,
modifiedData: {
...prev.modifiedData,
[name]: value,
},
}));
};
handleSubmit = async e => {
e.preventDefault();
const formData = new FormData();
Array.from(this.state.images).forEach(image => {
formData.append('files', image);
});
try {
const response = await axios.post('http://localhost:1337/api/animaux?populate=*',
{
"data": {
nom: this.state.modifiedData.nom,
Description: this.state.modifiedData.description,
image : this.images,
races: this.state.modifiedData.races
}
})
axios
.post(`http://localhost:1337/api/upload`, formData, {
headers: { 'Content-Type': 'multipart/form-data' },
})
console.log(response);
} catch (error) {
this.setState({ error });
}
};
renderCheckbox = race => {
const {
modifiedData: { races },
} = this.state;
const isChecked = races.includes(race.id);
const handleChange = () => {
if (!races.includes(race.id)) {
this.handleInputChange({
target: { name: 'races', value: races.concat(race.id) },
});
} else {
this.handleInputChange({
target: {
name: 'races',
value: races.filter(v => v !== race.id),
},
});
}
};
return (
<div key={race.id}>
<label htmlFor={race.id}>{race.attributes.nom}</label>
<input
type="checkbox"
checked={isChecked}
onChange={handleChange}
name="races"
id={race.id}
/>
</div>
);
};
render() {
const { error, allRaces, modifiedData } = this.state;
if (error) {
return <div>An error occured: {error.message}</div>;
}
return (
<div className="App">
<form onSubmit={this.handleSubmit}>
<h3>Ajouter un animal</h3>
<br />
<label>
Name:
<input
type="text"
name="nom"
onChange={this.handleInputChange}
value={modifiedData.name}
/>
</label>
<label>
Description:
<input
type="text"
name="description"
onChange={this.handleInputChange}
value={modifiedData.description}
/>
</label>
<input type="file" name="images" value={this.images} onChange={this.onImageChange}/>
<div>
<br />
<b>Select races</b>
{allRaces.map(this.renderCheckbox)}
</div>
<br />
<button type="submit">Ajouter</button>
</form>
</div>
);
}
}
export default AddAnimal;

'http://localhost:8000' has been blocked by CORS policy

I'm working on the Pro MERN Stack: Full Stack Web App Development with Mongo, Express, React, and Node book, and I ran into CORS policy errors whenever I tried to go back to my homepage. It looks like the error is coming from my graphqlFetch file but I'm not so sure what the issue is. Any insight would be extremely helpful!!
CORS policy error message
GraphQLFetch error
1:
My GraphQLFetch code:
import fetch from 'isomorphic-fetch';
const dateRegex = new RegExp('^\\d\\d\\d\\d-\\d\\d-\\d\\d');
function jsonDateReviver(key, value) {
if (dateRegex.test(value)) return new Date(value);
return value;
}
export default async function
graphQLFetch(query, variables = {}, showError = null, cookie = null) {
const apiEndpoint = (__isBrowser__) // eslint-disable-line no-undef
? window.ENV.UI_API_ENDPOINT
: process.env.UI_SERVER_API_ENDPOINT;
try {
const headers = { 'Content-Type': 'application/json' };
if (cookie) headers.Cookie = cookie;
const response = await fetch(apiEndpoint, {
method: 'POST',
credentials: 'include',
headers,
body: JSON.stringify({ query, variables }),
});
const body = await response.text();
const result = JSON.parse(body, jsonDateReviver);
if (result.errors) {
const error = result.errors[0];
if (error.extensions.code === 'BAD_USER_INPUT') {
const details = error.extensions.exception.errors.join('\n ');
if (showError) showError(`${error.message}:\n ${details}`);
} else if (showError) {
showError(`${error.extensions.code}: ${error.message}`);
}
}
return result.data;
} catch (e) {
if (showError) showError(`Error in sending data to server: ${e.message}`);
return null;
}
}
My IssueEdit file
import React from 'react';
import { Link } from 'react-router-dom';
import { LinkContainer } from 'react-router-bootstrap';
import {
Col, Panel, Form, FormGroup, FormControl, ControlLabel,
ButtonToolbar, Button, Alert,
} from 'react-bootstrap';
import graphQLFetch from './graphQLFetch.js';
import NumInput from './NumInput.jsx';
import DateInput from './DateInput.jsx';
import TextInput from './TextInput.jsx';
import Toast from './Toast.jsx';
import store from './store.js';
export default class IssueEdit extends React.Component {
static async fetchData(match, search, showError) {
const query = `query issue($id: Int!) {
issue(id: $id) {
id title status owner
effort created due description
}
}`;
const { params: { id } } = match;
const result = await graphQLFetch(query, { id }, showError);
return result;
}
constructor() {
super();
const issue = store.initialData ? store.initialData.issue : null;
delete store.initialData;
this.state = {
issue,
invalidFields: {},
showingValidation: false,
toastVisible: false,
toastMessage: '',
toastType: 'success',
};
this.onChange = this.onChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.onValidityChange = this.onValidityChange.bind(this);
this.dismissValidation = this.dismissValidation.bind(this);
this.showValidation = this.showValidation.bind(this);
this.showSuccess = this.showSuccess.bind(this);
this.showError = this.showError.bind(this);
this.dismissToast = this.dismissToast.bind(this);
}
componentDidMount() {
const { issue } = this.state;
if (issue == null) this.loadData();
}
componentDidUpdate(prevProps) {
const { match: { params: { id: prevId } } } = prevProps;
const { match: { params: { id } } } = this.props;
if (id !== prevId) {
this.loadData();
}
}
onChange(event, naturalValue) {
const { name, value: textValue } = event.target;
const value = naturalValue === undefined ? textValue : naturalValue;
this.setState(prevState => ({
issue: { ...prevState.issue, [name]: value },
}));
}
onValidityChange(event, valid) {
const { name } = event.target;
this.setState((prevState) => {
const invalidFields = { ...prevState.invalidFields, [name]: !valid };
if (valid) delete invalidFields[name];
return { invalidFields };
});
}
async handleSubmit(e) {
e.preventDefault();
this.showValidation();
const { issue, invalidFields } = this.state;
if (Object.keys(invalidFields).length !== 0) return;
const query = `mutation issueUpdate(
$id: Int!
$changes: IssueUpdateInputs!
) {
issueUpdate(
id: $id
changes: $changes
) {
id title status owner
effort created due description
}
}`;
const { id, created, ...changes } = issue;
const data = await graphQLFetch(query, { changes, id }, this.showError);
if (data) {
this.setState({ issue: data.issueUpdate });
this.showSuccess('Updated issue successfully');
}
}
async loadData() {
const { match } = this.props;
const data = await IssueEdit.fetchData(match, null, this.showError);
this.setState({ issue: data ? data.issue : {}, invalidFields: {} });
}
showValidation() {
this.setState({ showingValidation: true });
}
dismissValidation() {
this.setState({ showingValidation: false });
}
showSuccess(message) {
this.setState({
toastVisible: true, toastMessage: message, toastType: 'success',
});
}
showError(message) {
this.setState({
toastVisible: true, toastMessage: message, toastType: 'danger',
});
}
dismissToast() {
this.setState({ toastVisible: false });
}
render() {
const { issue } = this.state;
if (issue == null) return null;
const { issue: { id } } = this.state;
const { match: { params: { id: propsId } } } = this.props;
if (id == null) {
if (propsId != null) {
return <h3>{`Issue with ID ${propsId} not found.`}</h3>;
}
return null;
}
const { invalidFields, showingValidation } = this.state;
let validationMessage;
if (Object.keys(invalidFields).length !== 0 && showingValidation) {
validationMessage = (
<Alert bsStyle="danger" onDismiss={this.dismissValidation}>
Please correct invalid fields before submitting.
</Alert>
);
}
const { issue: { title, status } } = this.state;
const { issue: { owner, effort, description } } = this.state;
const { issue: { created, due } } = this.state;
const { toastVisible, toastMessage, toastType } = this.state;
return (
<Panel>
<Panel.Heading>
<Panel.Title>{`Editing issue: ${id}`}</Panel.Title>
</Panel.Heading>
<Panel.Body>
<Form horizontal onSubmit={this.handleSubmit}>
<FormGroup>
<Col componentClass={ControlLabel} sm={3}>Created</Col>
<Col sm={9}>
<FormControl.Static>
{created.toDateString()}
</FormControl.Static>
</Col>
</FormGroup>
<FormGroup>
<Col componentClass={ControlLabel} sm={3}>Status</Col>
<Col sm={9}>
<FormControl
componentClass="select"
name="status"
value={status}
onChange={this.onChange}
>
<option value="New">New</option>
<option value="Assigned">Assigned</option>
<option value="Fixed">Fixed</option>
<option value="Closed">Closed</option>
</FormControl>
</Col>
</FormGroup>
<FormGroup>
<Col componentClass={ControlLabel} sm={3}>Owner</Col>
<Col sm={9}>
<FormControl
componentClass={TextInput}
name="owner"
value={owner}
onChange={this.onChange}
key={id}
/>
</Col>
</FormGroup>
<FormGroup>
<Col componentClass={ControlLabel} sm={3}>Effort</Col>
<Col sm={9}>
<FormControl
componentClass={NumInput}
name="effort"
value={effort}
onChange={this.onChange}
key={id}
/>
</Col>
</FormGroup>
<FormGroup validationState={
invalidFields.due ? 'error' : null
}
>
<Col componentClass={ControlLabel} sm={3}>Due</Col>
<Col sm={9}>
<FormControl
componentClass={DateInput}
onValidityChange={this.onValidityChange}
name="due"
value={due}
onChange={this.onChange}
key={id}
/>
<FormControl.Feedback />
</Col>
</FormGroup>
<FormGroup>
<Col componentClass={ControlLabel} sm={3}>Title</Col>
<Col sm={9}>
<FormControl
componentClass={TextInput}
size={50}
name="title"
value={title}
onChange={this.onChange}
key={id}
/>
</Col>
</FormGroup>
<FormGroup>
<Col componentClass={ControlLabel} sm={3}>Description</Col>
<Col sm={9}>
<FormControl
componentClass={TextInput}
tag="textarea"
rows={4}
cols={50}
name="description"
value={description}
onChange={this.onChange}
key={id}
/>
</Col>
</FormGroup>
<FormGroup>
<Col smOffset={3} sm={6}>
<ButtonToolbar>
<Button bsStyle="primary" type="submit">Submit</Button>
<LinkContainer to="/issues">
<Button bsStyle="link">Back</Button>
</LinkContainer>
</ButtonToolbar>
</Col>
</FormGroup>
<FormGroup>
<Col smOffset={3} sm={9}>{validationMessage}</Col>
</FormGroup>
</Form>
</Panel.Body>
<Panel.Footer>
<Link to={`/edit/${id - 1}`}>Prev</Link>
{' | '}
<Link to={`/edit/${id + 1}`}>Next</Link>
</Panel.Footer>
<Toast
showing={toastVisible}
onDismiss={this.dismissToast}
bsStyle={toastType}
>
{toastMessage}
</Toast>
</Panel>
);
}
}
My IssueList file:
import React from 'react';
import URLSearchParams from 'url-search-params';
import { Panel } from 'react-bootstrap';
import IssueFilter from './IssueFilter.jsx';
import IssueTable from './IssueTable.jsx';
import IssueDetail from './IssueDetail.jsx';
import graphQLFetch from './graphQLFetch.js';
import withToast from './withToast.jsx';
import store from './store.js';
class IssueList extends React.Component {
static async fetchData(match, search, showError) {
const params = new URLSearchParams(search);
const vars = { hasSelection: false, selectedId: 0 };
if (params.get('status')) vars.status = params.get('status');
const effortMin = parseInt(params.get('effortMin'), 10);
if (!Number.isNaN(effortMin)) vars.effortMin = effortMin;
const effortMax = parseInt(params.get('effortMax'), 10);
if (!Number.isNaN(effortMax)) vars.effortMax = effortMax;
const { params: { id } } = match;
const idInt = parseInt(id, 10);
if (!Number.isNaN(idInt)) {
vars.hasSelection = true;
vars.selectedId = idInt;
}
const query = `query issueList(
$status: StatusType
$effortMin: Int
$effortMax: Int
$hasSelection: Boolean!
$selectedId: Int!
) {
issueList(
status: $status
effortMin: $effortMin
effortMax: $effortMax
) {
id title status owner
created effort due
}
issue(id: $selectedId) #include (if : $hasSelection) {
id description
}
}`;
const data = await graphQLFetch(query, vars, showError);
return data;
}
constructor() {
super();
const issues = store.initialData ? store.initialData.issueList : null;
const selectedIssue = store.initialData
? store.initialData.issue
: null;
delete store.initialData;
this.state = {
issues,
selectedIssue,
};
this.closeIssue = this.closeIssue.bind(this);
this.deleteIssue = this.deleteIssue.bind(this);
}
componentDidMount() {
const { issues } = this.state;
if (issues == null) this.loadData();
}
componentDidUpdate(prevProps) {
const {
location: { search: prevSearch },
match: { params: { id: prevId } },
} = prevProps;
const { location: { search }, match: { params: { id } } } = this.props;
if (prevSearch !== search || prevId !== id) {
this.loadData();
}
}
async loadData() {
const { location: { search }, match, showError } = this.props;
const data = await IssueList.fetchData(match, search, showError);
if (data) {
this.setState({ issues: data.issueList, selectedIssue: data.issue });
}
}
async closeIssue(index) {
const query = `mutation issueClose($id: Int!) {
issueUpdate(id: $id, changes: { status: Closed }) {
id title status owner
effort created due description
}
}`;
const { issues } = this.state;
const { showError } = this.props;
const data = await graphQLFetch(query, { id: issues[index].id },
showError);
if (data) {
this.setState((prevState) => {
const newList = [...prevState.issues];
newList[index] = data.issueUpdate;
return { issues: newList };
});
} else {
this.loadData();
}
}
async deleteIssue(index) {
const query = `mutation issueDelete($id: Int!) {
issueDelete(id: $id)
}`;
const { issues } = this.state;
const { location: { pathname, search }, history } = this.props;
const { id } = issues[index];
const { showSuccess, showError } = this.props;
const data = await graphQLFetch(query, { id }, showError);
if (data && data.issueDelete) {
this.setState((prevState) => {
const newList = [...prevState.issues];
if (pathname === `/issues/${id}`) {
history.push({ pathname: '/issues', search });
}
newList.splice(index, 1);
return { issues: newList };
});
showSuccess(`Deleted issue ${id} successfully.`);
} else {
this.loadData();
}
}
render() {
const { issues } = this.state;
if (issues == null) return null;
const { selectedIssue } = this.state;
return (
<React.Fragment>
<Panel>
<Panel.Heading>
<Panel.Title toggle>Filter</Panel.Title>
</Panel.Heading>
<Panel.Body collapsible>
<IssueFilter />
</Panel.Body>
</Panel>
<IssueTable
issues={issues}
closeIssue={this.closeIssue}
deleteIssue={this.deleteIssue}
/>
<IssueDetail issue={selectedIssue} />
</React.Fragment>
);
}
}
const IssueListWithToast = withToast(IssueList);
IssueListWithToast.fetchData = IssueList.fetchData;
export default IssueListWithToast;
You have to allow cross origin on your graphql server. For security reasons browsers didn't allow ajax request on cross origin. So lets say you're on localhost:3000 and your server is running on localhost:8000 so these two are on different origins.
So use cors module on Express server and allow Access-Control-Allow-Origin to "*"

How to prop an input value into a parameter for an API call

I have a Header.js component that takes a user's input and updates its state. I want to transfer(prop?) this item into the parent component App.js where it will be put in as a parameter and the data will be console logged relative to the user's input. I don't know how to transfer the state and implement it into the API's parameter.
class Header extends Component {
constructor() {
super();
this.state = {
query: '',
}
}
handleSubmit = (e) => {
e.preventDefault();
// form's input value
let userSearch = this.state.query;
}
handleChange = (e) => {
this.setState({
query: e.target.value
});
}
render() {
return (
<header>
<form onSubmit={this.handleSubmit}>
<input
onChange={this.handleChange}
type="text"
placeholder="Search"
/>
<label className="sr-only" htmlFor="search">Search News</label>
</form>
</header>
)
}
}
export default Header
import Header from './Components/Header'
import axios from 'axios';
class App extends Component {
constructor() {
super();
this.state = {
articles: [],
}
}
componentDidMount() {
axios({
// I want this.state.query in header.js to be {parameter}
url: 'http://newsapi.org/v2/everything?q={parameter}&sortBy=popularity&apiKey=where-the-key-goes',
method: 'GET',
responseType: 'JSON',
}).then((response => {
let articles = response.data.articles;
this.setState({
articles,
isLoading: false,
})
console.log(articles);
}))
}
render() {
return (
<>
<Header />
</>
)
}
}
export default App
You could create a callback function in the App component and pass to Header as a prop:
class App extends Component {
...
handleSearch = (value) => {
axios({
url: `http://newsapi.org/v2/everything?q=${value}&sortBy=popularity&apiKey=where-the-key-goes`,
method: "GET",
responseType: "JSON",
}).then((response) => { ... });
};
render() {
return (
<>
<Header handleSearch={this.handleSearch} />
</>
);
}
}
Then use it in the Header's handleSubmit function:
handleSubmit = (e) => {
e.preventDefault();
// form's input value
let userSearch = this.state.query;
this.props.handleSearch(userSearch);
};
class Header extends Component<Props> { // add Props
...
handleSubmit = (e) => {
e.preventDefault();
// form's input value
let userSearch = this.state.query;
this.props.onValueSet(userSearch); // callback
}
...
}
class App extends Component {
...
// add callback
_setValueHandle = (value) => {
console.log(value);
this.setState({parameter: value}); // do something u want
};
render() {
return (
<>
{/* set callback */}
<Header onValueSet={this._setValueHandle} />
</>
)}
...
}
how about this?
You have to add props from App.js. Also you don't need to call the api on componentDidMount because you want have the query yet. Try this:
class Header extends Component {
static defaultProps = {
onUpdate: () => {},
onSubmission: () => {}
}
constructor() {
super();
this.state = {
query: '',
}
}
handleSubmit = (e) => {
e.preventDefault();
// form's input value
let userSearch = this.state.query;
this.props.onSubmission(this.state.query); //Send submission to parent
}
handleChange = (e) => {
this.setState({
query: e.target.value
}, () => {
this.props.onUpdate(this.state.query); //Send change to parent
});
}
render() {
return (
<header>
<form onSubmit={this.handleSubmit.bind(this)}>
<input
onChange={this.handleChange.bind(this)}
type="text"
placeholder="Search"
/>
<label className="sr-only" htmlFor="search">Search News</label>
</form>
</header>
)
}
}
export default Header
import Header from './Components/Header'
import axios from 'axios';
class App extends Component {
constructor() {
super();
this.state = {
articles: [],
query: ""
}
}
componentDidMount() {
}
request(query){
axios({
// I want this.state.query in header.js to be {parameter}
//NOTE: Query could also be this.state.query since we're updating it on change
url: 'http://newsapi.org/v2/everything?q={parameter}&sortBy=popularity&apiKey=where-the-key-goes',
method: 'GET',
responseType: 'JSON',
}).then((response => {
let articles = response.data.articles;
this.setState({
articles,
isLoading: false,
})
console.log(articles);
}))
}
render() {
return (
<>
<Header onUpdate={query => this.setState({query: query})} onSubmission={this.request.bind(this)} />
</>
)
}
}
export default App

Set input value automatically on a fetch request

I present my problem to you
In the following code, I'm trying to retrieve phone numbers from an API and then show them in a Card; in each card, I have a different number which is displayed
and also in each card, I have an input field to enter the phone number which I obtained before.
My problem is that I don't want to fill in the input manually with the recovered number.
So basically I would like to start my function without having to fill in this field manually.
Do you have any idea how to do this?
I tried to simplify the code so that it is as clear as possible
Thanks for your help Neff
import React, { Component } from 'react';
import { CardText, Card,Row, Col, CardTitle, Button } from 'reactstrap';
import axios from 'axios'
const entrypoint = process.env.REACT_APP_API_ENTRYPOINT+'/api';
class AdminPage extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
message: {
to: '',
body: 'hola amigo :)'
},
submitting: false,
error: false
};
this.onHandleChange = this.onHandleChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
}
onSubmit(event) {
event.preventDefault();
this.setState({ submitting: true });
fetch('/api/messages', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(this.state.message)
})
.then(res => res.json())
.then(data => {
if (data.success) {
this.setState({
error: false,
submitting: false,
message: {
to: '',
body: ''
}
});
} else {
this.setState({
error: true,
submitting: false
});
}
});
}
// rest of the component
onHandleChange(event) {
const name = event.target.getAttribute('name');
this.setState({
message: { ...this.state.message, [name]: event.target.value }
});
}
getRandom = async () => {
const res = await axios.get(
entrypoint + "/alluserpls"
)
this.setState({ data: res.data })
}
componentDidMount() {
this.getRandom()
}
render() {
let datas = this.state.data.map(datass => {
const status = JSON.parse(localStorage.getItem("validated-order")||"{}")[datass.id];
return (
<div>
< Col sm="12" key={datass.id} className="wtfFuHereIsForOnlyBackGroundColorForCol12Nice">
<div key="a">
<Card body className="yoloCardBody">
<CardText> Téléphone {datass.phone}</CardText>
<form
onSubmit={this.onSubmit}
className={this.state.error ? 'error sms-form' : 'sms-form'} >
<div>
<input
type="tel"
name="to"
id="to"
value={this.state.message.to}
onChange={this.onHandleChange}
/>
</div>
<Button className="buttonForLancerMaybe" type="submit" disabled=
{this.state.submitting}>SMS</Button>
</form>
</Card>
</div>
</Col>
</div>
)
})
return (
<div> <div>
<div>
{datas}
</div>
</div>
</div>
<div className="box">
</div>
</div>
)
}
}
export default AdminPage
So I guess this little change in your code will help you, separating the logic and making a new component for your form section would be your solution. say we have a component called "SmsForm" so first, you need to import it in your current component:
import SmsForm from "../SmsForm/Loadable";
and then you pass your phone number as a prop to this SmsForm like this:
let datas = this.state.data.map(datass => {
const status = JSON.parse(localStorage.getItem("validated-order") || "{}")[datass.id];
return (
<div>
< Col sm="12" key={datass.id} className="wtfFuHereIsForOnlyBackGroundColorForCol12Nice">
<GridLayout className="GridlayoutTextOnlyForGridOuiAndHeigthbecauseHeigthWasBug" layout={layout} cols={12} rowHeight={30} width={1200}>
<div key="a">
<Card body className="yoloCardBody">
<CardText> Téléphone {datass.phone}</CardText>
<SmsForm phone={datass.phone}/>
</Card>
</div>
</GridLayout>
</ Col>
</div>
)
})
and SmsForm would be sth like this:
import React from 'react';
...
export class SmsForm extends React.Component {
constructor(props) {
super(props);
this.state = {
message: {
to: props.phone,
body: 'hola amigo :)'
},
submitting: false,
error: false
};
this.onHandleChange = this.onHandleChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
}
onSubmit(event) {
event.preventDefault();
this.setState({ submitting: true });
fetch('/api/messages', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(this.state.message)
})
.then(res => res.json())
.then(data => {
if (data.success) {
this.setState({
error: false,
submitting: false,
message: {
to: '',
body: ''
}
});
} else {
this.setState({
error: true,
submitting: false
});
}
});
}
// rest of the component
onHandleChange(event) {
const name = event.target.getAttribute('name');
this.setState({
message: { ...this.state.message, [name]: event.target.value }
});
}
render() {
return (
<form
onSubmit={this.onSubmit}
className={this.state.error ? 'error sms-form' : 'sms-form'} >
<div>
<input type="tel" name="to" id="to" value={datass.phone} onChange={e => this.onHandleChange(e, e.target.value)}/>
</div>
<Button className="buttonForLancerMaybe" type="submit" disabled=
{this.state.submitting}>SMS</Button>
</form>
);
}
}
export default SmsForm;

How to use the upload control from ant design, to get a reference of the file

I have the following component and it works perfect.
import React, { Component } from 'react';
import { Row, Col } from 'antd';
import PageHeader from '../../components/utility/pageHeader';
import Box from '../../components/utility/box';
import LayoutWrapper from '../../components/utility/layoutWrapper.js';
import ContentHolder from '../../components/utility/contentHolder';
import basicStyle from '../../settings/basicStyle';
import IntlMessages from '../../components/utility/intlMessages';
import { adalApiFetch } from '../../adalConfig';
import RegisterTenantForm from './registertenantform';
export default class extends Component {
constructor(props) {
super(props);
this.state = {TenantId: '', TenantUrl: '', CertificatePassword: '' };
this.handleChangeTenantUrl = this.handleChangeTenantUrl.bind(this);
this.handleChangeCertificatePassword = this.handleChangeCertificatePassword.bind(this);
this.handleChangeTenantId= this.handleChangeTenantId.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
};
handleChangeTenantUrl(event){
this.setState({TenantUrl: event.target.value});
}
handleChangeCertificatePassword(event){
this.setState({CertificatePassword: event.target.value});
}
handleChangeTenantId(event){
this.setState({TenantId: event.target.value});
}
handleSubmit(event){
event.preventDefault();
let data = new FormData();
//Append files to form data
data.append("model", JSON.stringify({ "TenantId": this.state.TenantId, "TenantUrl": this.state.TenantUrl, "CertificatePassword": this.state.CertificatePassword }));
//data.append("model", {"TenantId": this.state.TenantId, "TenantUrl": this.state.TenantUrl, "TenantPassword": this.state.TenantPassword });
let files = this.state.selectedFiles;
for (let i = 0; i < files.length; i++) {
data.append("file", files[i], files[i].name);
}
const options = {
method: 'put',
body: data,
config: {
headers: {
'Content-Type': 'multipart/form-data'
}
}
};
adalApiFetch(fetch, "/Tenant", options)
.then(response => response.json())
.then(responseJson => {
if (!this.isCancelled) {
this.setState({ data: responseJson });
}
})
.catch(error => {
console.error(error);
});
}
upload(e){
let files = e.target.files;
this.setState({ 'selectedFiles': files });
}
render(){
const { data } = this.state;
const { rowStyle, colStyle, gutter } = basicStyle;
return (
<div>
<LayoutWrapper>
<PageHeader>{<IntlMessages id="pageTitles.TenantAdministration" />}</PageHeader>
<Row style={rowStyle} gutter={gutter} justify="start">
<Col md={12} sm={12} xs={24} style={colStyle}>
<Box
title={<IntlMessages id="pageTitles.TenantAdministration" />}
subtitle={<IntlMessages id="pageTitles.TenantAdministration" />}
>
<ContentHolder>
<form onSubmit={this.handleSubmit}>
<label>
TenantId:
<input type="text" value={this.state.TenantId} onChange={this.handleChangeTenantId} />
</label>
<label>
TenantUrl:
<input type="text" value={this.state.TenantUrl} onChange={this.handleChangeTenantUrl} />
</label>
<label>
TenantPassword:
<input type="text" value={this.state.CertificatePassword} onChange={this.handleChangeCertificatePassword} />
</label>
<label>
Certificate:
<input onChange = { e => this.upload(e) } type = "file" id = "files" ref = { file => this.fileUpload } />
</label>
<input type="submit" value="Submit" />
</form>
</ContentHolder>
</Box>
</Col>
</Row>
</LayoutWrapper>
</div>
);
}
}
Now, I need a nice design, I am using antd form components, and from the design point of view, everything is looking nice.
However, I am having a problem with handlesubmit, because e.target.files is undefined.
How can I use the upload control to put the file on the state when the control changes?
My work so far, problem is in e.target.files
import React, { Component } from 'react';
import { Input, Upload , Icon} from 'antd';
import Form from '../../components/uielements/form';
import Checkbox from '../../components/uielements/checkbox';
import Button from '../../components/uielements/button';
import Notification from '../../components/notification';
import { adalApiFetch } from '../../adalConfig';
const FormItem = Form.Item;
class RegisterTenantForm extends Component {
constructor(props) {
super(props);
this.state = {TenantId: '', TenantUrl: '', CertificatePassword: '' };
this.handleChangeTenantUrl = this.handleChangeTenantUrl.bind(this);
this.handleChangeCertificatePassword = this.handleChangeCertificatePassword.bind(this);
this.handleChangeTenantId= this.handleChangeTenantId.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
};
handleChangeTenantUrl(event){
this.setState({TenantUrl: event.target.value});
}
handleChangeCertificatePassword(event){
this.setState({CertificatePassword: event.target.value});
}
handleChangeTenantId(event){
this.setState({TenantId: event.target.value});
}
handleupload(e){
let files = e.target.files;
this.setState({ 'selectedFiles': files });
}
state = {
confirmDirty: false,
};
handleSubmit(e){
e.preventDefault();
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
/*Notification(
'success',
'Received values of form',
JSON.stringify(values)
);*/
let data = new FormData();
//Append files to form data
data.append("model", JSON.stringify({ "TenantId": this.state.TenantId, "TenantUrl": this.state.TenantUrl, "CertificatePassword": this.state.CertificatePassword }));
//data.append("model", {"TenantId": this.state.TenantId, "TenantUrl": this.state.TenantUrl, "TenantPassword": this.state.TenantPassword });
let files = this.state.selectedFiles;
for (let i = 0; i < files.length; i++) {
data.append("file", files[i], files[i].name);
}
const options = {
method: 'put',
body: data,
config: {
headers: {
'Content-Type': 'multipart/form-data'
}
}
};
adalApiFetch(fetch, "/Tenant", options)
.then(response => response.json())
.then(responseJson => {
if (!this.isCancelled) {
this.setState({ data: responseJson });
}
})
.catch(error => {
console.error(error);
});
}
});
}
render() {
const { getFieldDecorator } = this.props.form;
const formItemLayout = {
labelCol: {
xs: { span: 24 },
sm: { span: 6 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 14 },
},
};
const tailFormItemLayout = {
wrapperCol: {
xs: {
span: 24,
offset: 0,
},
sm: {
span: 14,
offset: 6,
},
},
};
return (
<Form onSubmit={this.handleSubmit}>
<FormItem {...formItemLayout} label="Tenant Id" hasFeedback>
{getFieldDecorator('tenantid', {
rules: [
{
required: true,
message: 'Please input your tenant id',
},
],
})(<Input name="tenantid" id="tenantid" onChange={this.handleChangeTenantId}/>)}
</FormItem>
<FormItem {...formItemLayout} label="Certificate Password" hasFeedback>
{getFieldDecorator('certificatepassword', {
rules: [
{
required: true,
message: 'Please input your password!',
}
],
})(<Input type="certificatepassword" onChange={this.handleChangeCertificatePassword}/>)}
</FormItem>
<FormItem {...formItemLayout} label="Tenant admin url" hasFeedback>
{getFieldDecorator('tenantadminurl', {
rules: [
{
required: true,
message: 'Please input your tenant admin url!',
}
],
})(<Input type="tenantadminurl" onChange={this.handleChangeTenantUrl} />)}
</FormItem>
<FormItem {...tailFormItemLayout}>
<Upload accept=".png" onChange={this.handleupload}>
<Button>
<Icon type="upload" /> Click to Upload
</Button>
</Upload>
<Button type="primary" htmlType="submit">
Register tenant
</Button>
</FormItem>
</Form>
);
}
}
const WrappedRegisterTenantForm = Form.create()(RegisterTenantForm);
export default WrappedRegisterTenantForm;
Documentation, which is not clear for me:
https://ant.design/components/upload/
Accordingly to documentation it seems that instead of trying to retrieve files list from e.target
handleupload(e) {
let files = e.target.files;
this.setState({ 'selectedFiles': files });
}
you should use antd's API and write something like next:
handleupload(info) {
this.setState({ 'selectedFiles': info.fileList });
}
Also please pay attention to checking of files uploading statuses (info.file.status) and consider examples which make Upload component controlled.
I prefer beforeUpload. It accepts two args file and fileList, and if it returns false, then upload skipped :
handleupload(file, fileList){
this.setState({ 'selectedFiles': fileList });
}
...
<Upload beforeUpload={this.handleupload} ... />
Ant Design Upload component is designed for backend upload/process ; what you are doing is frontend upload/process; so use beforeUpload -works great
const frontendUpload=(file,fileList)=>{
// parseTheFile (file);
fileList.forEach(f=>parseTheFile(f))
}
Return (
<div>
<Upload beforeUpload={(file, fileList)=>{frontendUpload(file,fileList)}}>
<Button icon={<UploadOutlined />}>Click to Upload</Button>
</Upload>
</div>
)
you can use the maxCount props that comes with the upload component to set limit to files uploaded

Categories

Resources