I have a student who has an app that will host a photo to cloudinary then store it in his database. Everything worked fine locally but when he tried to host his app on heroku his app couldn't find his cloudinary environment variables. As far as I know he has done everything right and his app can find his other variables just not the cloudinary ones. Has anyone run into a problem similar to this and can give me any direction?
import React, { Component } from 'react';
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome';
import Dropzone from 'react-dropzone';
import ReactQuill from 'react-quill';
import request from 'superagent';
const CLOUDINARY_UPLOAD_PRESET = process.env.CLOUDINARY_UPLOAD_PRESET
const CLOUDINARY_UPLOAD_URL = process.env.CLOUDINARY_UPLOAD_URL
export default class UpdateBook extends Component {
constructor(props){
super(props);
this.state={
id: "",
title: "",
blog_status: "",
content: "",
featured_image_url: "",
formHidden: true,
uploadedFile:'',
uploadedFileCloudinaryUrl: '',
editMode: false
}
this.handleChange = this.handleChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
this.editBlog = this.editBlog.bind(this)
this.handleContentChange = this.handleContentChange.bind(this)
this.handleImageDrop = this.handleImageDrop.bind(this)
this.componentConfig=this.componentConfig.bind(this);
this.djsConfig=this.djsConfig.bind(this);
this.deleteImage = this.deleteImage.bind(this);
}
handleChange(event){
this.setState({
[event.target.name]: event.target.value
})
}
handleContentChange(value) {
this.setState({ content: value })
}
handleSubmit(event){
let id = this.state.id
let title = this.state.title;
let blog_status = this.state.blog_status;
let content = this.state.content;
let featured_image_url = this.state.featured_image_url;
fetch(`https://rwtw-backend-tw.herokuapp.com/update_blog/${id}`, {
method: "PUT",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({title: title, blog_status: blog_status, content: content, featured_image_url: featured_image_url})
}).then(response =>{
response.json()
}).then(responseData =>{
return responseData
}).catch(error => console.log("Fetch error", error))
}
handleImageDrop(files){
this.setState({
uploadedFile: files[0]
})
const currentFile = files[0]
const myFileItemReader = new FileReader()
myFileItemReader.addEventListener("load", () => {
this.setState({
image_src: myFileItemReader.result
})
}, false)
myFileItemReader.readAsDataURL(currentFile)
let upload = request.post(CLOUDINARY_UPLOAD_URL)
.field("upload_preset", CLOUDINARY_UPLOAD_PRESET)
.field("file", this.state.uploadedFile);
upload.end((err, response) => {
if (err){
console.log(err)
} if (response.body.secure_url !== ""){
this.setState({
featured_image_url: response.body.secure_url
})
}
})
}
editBlog(){
this.setState({editMode: true})
this.setState({id: this.props.ourProp[0]})
this.setState({title: this.props.ourProp[1]})
this.setState({blog_status: this.props.ourProp[2]})
this.setState({content: this.props.ourProp[3]})
this.setState({featured_image_url: this.props.ourProp[4]})
}
componentConfig(){
return{
iconFileTypes: [".jpg", ".png"],
showFiletypeIcon: true,
postUrl: 'https://httpbin.org/post'
}
}
djsConfig(){
return{
addRemoveLinks: true,
maxFiles: 1
}
}
deleteImage(){
this.setState({
featured_image_url: ""
})
}
render(){
return (
<div>
{this.state.editMode ?
<form>
<div className="blog-manager-title">
<input
type="text"
name="title"
placeholder="Blog Title"
value = {this.state.title}
onChange = {this.handleChange}
/>
</div>
<div className="blog-manager-blog_status">
<select
type="text"
name="blog_status"
value = {this.state.blog_status}
onChange = {this.handleChange}
>
<option value="draft">Draft</option>
<option value="published">Published</option>
</select>
</div>
<div className="blog-manager-content">
<ReactQuill
value={this.state.content}
onChange={this.handleContentChange}
/>
</div>
<div>
{this.state.featured_image_url !== "" ?
<div>
<img src={this.state.featured_image_url} style={{width: '400px'}}/>
<div className="image-removal-link">
<a onClick={() => this.deleteImage()}>Remove Image</a>
</div>
</div > :
<Dropzone
onDrop={this.handleImageDrop}
multiple= {false}
accept="image/*"
>
Add a picture
</Dropzone>
}
</div>
<div className="submit">
<button onClick={this.handleSubmit} value="submit">Add Blog</button>
</div>
</form> : null}
<button onClick={this.editBlog}><FontAwesomeIcon icon="edit"/></button>
</div>
);
}
}
In Heroku, there is a Cloudinary add-on. This will create a new Cloudinary account. So if your student create Cloudinary account outside Heroku, this will be 2 different account.
To double check this, from their Heroku account, try to login to Cloudinary, check if it's using the same cloud name.
Related
I'm using draft.js to make a text editor and I have two components: CreatePost.js which gets the post fields from the back end and populates the state with the user input and TextEditor.js which contains a text editor which I am using in CreatePost.js. The text editor should populate the body field in the state of CreatePost.js onChange.
My question is how can I get the text editor to populate the state in the other component? Would I need to use props instead?
Before, I had a text area in CreatePost.js which populated the body. I want the text editor in the other component to populate it instead. I've tried using
<TextEditor onChange={this.changeHandler} value={body} /> in CreatePost.js but it didn't work.
console.log(body):
posts.js (controller)
exports.create = (req, res) => {
const { title, body, date } = req.body;
const post = new Post({
title,
body,
date,
"author.id": req.profile._id,
"author.name": req.profile.name,
});
post
.save()
.then((response) => {
res.send(response);
})
.catch((err) => {
return res.status(400).json({
error: errorHandler(err),
});
});
};
CreatePost.js
class CreatePost extends React.Component {
constructor(props) {
super(props);
this.state = {
title: "",
body: "",
createdPost: "",
error: "",
};
}
changeHandler = (e) => {
this.setState({ [e.target.name]: e.target.value });
};
submitHandler = (e) => {
e.preventDefault();
const {
user: { _id },
} = isAuthenticated();
axios({
url: `${API}/post/new-post/${_id}`,
method: "POST",
data: this.state,
})
.then((response) => {
this.setState({ createdPost: this.state.title });
return response;
})
.catch((error) => {
if (!this.state.title || !this.state.body) {
this.setState({
error: "This post must contain a title and a body.",
});
}
console.log(error);
});
};
...
render() {
const { title, body } = this.state;
return (
<>
<Navbar />
<Tabs>
<TabList className="tabs">
<Tab className="tab">Draft</Tab>
<Tab className="tab">Preview</Tab>
</TabList>
<TabPanel>
<div className="newpost_container">
<form className="newpost_form" onSubmit={this.submitHandler}>
<div className="form-group">
<input
type="text"
placeholder="Title"
name="title"
className="newpost_field newpost_title"
onChange={this.changeHandler}
value={title}
/>
</div>
<div className="form-group newpost_body">
<TextEditor />
</div>
<button className="btn publish-post-btn" type="submit">
Publish
</button>
{this.showSuccess()}
{this.showError()}
</form>
</div>
</TabPanel>
<TabPanel>
<div>
<h1>{title}</h1>
<div>{body}</div>
</div>
</TabPanel>
</Tabs>
</>
);
}
}
export default CreatePost;
TextEditor.js
class TextEditor extends React.Component {
constructor(props) {
super(props);
this.state = {
editorState: EditorState.createEmpty(),
};
this.plugins = [addLinkPlugin];
}
toggleBlockType = (blockType) => {
this.onChange(RichUtils.toggleBlockType(this.state.editorState, blockType));
};
onChange = (editorState) => {
this.setState({
editorState,
});
};
handleKeyCommand = (command) => {
const newState = RichUtils.handleKeyCommand(
this.state.editorState,
command
);
if (newState) {
this.onChange(newState);
return "handled";
}
return "not-handled";
};
// onClick for format options
onAddLink = () => {
const editorState = this.state.editorState;
const selection = editorState.getSelection();
const link = window.prompt("Paste the link -");
if (!link) {
this.onChange(RichUtils.toggleLink(editorState, selection, null));
return "handled";
}
const content = editorState.getCurrentContent();
const contentWithEntity = content.createEntity("LINK", "MUTABLE", {
url: link,
});
const newEditorState = EditorState.push(
editorState,
contentWithEntity,
"create-entity"
);
const entityKey = contentWithEntity.getLastCreatedEntityKey();
this.onChange(RichUtils.toggleLink(newEditorState, selection, entityKey));
};
toggleBlockType = (blockType) => {
this.onChange(RichUtils.toggleBlockType(this.state.editorState, blockType));
};
render() {
return (
<div className="editorContainer">
<div className="toolbar">
<BlockStyleToolbar
editorState={this.state.editorState}
onToggle={this.toggleBlockType}
/>
// format buttons
</div>
<div>
<Editor
placeholder="Post Content"
blockStyleFn={getBlockStyle}
editorState={this.state.editorState}
handleKeyCommand={this.handleKeyCommand}
onChange={this.onChange}
plugins={this.plugins}
placeholder="Post Content"
/>
</div>
</div>
);
}
}
export default TextEditor;
It looks like you've been quite close to solving this actually. You were on the right path when sending down the change handler using props to the TextEditor. One solution to your problem is to move up the editorState to your CreatePost component and then pass the value and the change handler downwards. If you are doing this you should remove the editorState and the change handler for it from the TextEditor file. Just by continuing on your example something like this should work, I haven't tried the code out but it should help you in the right direction.
In CreatePost.js
constructor(props) {
super(props);
this.state = {
title: "",
body: EditorState.createEmpty(),
createdPost: "",
error: "",
};
}
....
<TextEditor onChange={(value) => this.setState({ body: value })} editorState={body} />
In TextEditor.js
<Editor
placeholder="Post Content"
blockStyleFn={getBlockStyle}
editorState={this.props.editorState}
handleKeyCommand={this.handleKeyCommand}
onChange={this.props.onChange}
plugins={this.plugins}
placeholder="Post Content"
/>
When posting the data we need to access the content of the editor instead of the EditorState. We can do this through draft.js API (see more here: https://draftjs.org/docs/api-reference-editor-state/#getcurrentcontent). And that's not enough unfortunately. We also need to to convert the content to a format that's easier to handle. We can do this with draft.js convertToRaw which you also need to import from the library (https://draftjs.org/docs/api-reference-data-conversion/#converttoraw). Convert to raw returns a JS object so we also need to convert that to a string before being able to send it to the server by using JSON.stringify().
axios({
url: `${API}/post/new-post/${_id}`,
method: "POST",
data: {
...this.state,
body: JSON.stringify(convertToRaw(this.state.body.getCurrentContent()))
}
})
Within my GigRegister component, I have an auth listener checking for auth status, and within that auth listener, I have a axios GET request fetching data that is then filtered through, and set to state:
authListener() {
auth().onAuthStateChanged((user) => {
if (user) {
this.setState({
userDetails: user,
isLoggedIn: true
});
axios
.get(
"https://us-central1-gig-fort.cloudfunctions.net/api/getGigListings"
)
.then((res) => {
let filteredGigs = res.data.filter((gig) => {
return gig.user === this.state.userDetails.uid;
});
this.setState({
filterGigs: filteredGigs,
});
});
} else {
this.setState({
userDetails: null,
});
console.log("no user signed in");
}
});
}
componentDidMount() {
this.authListener();
}
However, this is causing some issue with how to Gig Regiester page loads - it doesn't load the first time, but it does when the page is refreshed. Here's the initial error message:
Unhandled Rejection (TypeError): Cannot read property 'uid' of null
....and here's the entire component:
import React from "react";
import Header from "./Header";
import TextField from "#material-ui/core/TextField";
import Button from "#material-ui/core/Button";
import axios from "axios";
import * as firebase from 'firebase'
import { auth } from 'firebase/app'
import {Link} from 'react-router-dom'
import UniqueVenueListing from './UniqueVenueListing'
class GigRegister extends React.Component {
constructor() {
super();
this.state = {
name: "",
venue: "",
time: "",
date: "",
genre: "",
tickets: "",
price: "",
userDetails:{},
filterGigs:[]
};
this.handleSubmit = this.handleSubmit.bind(this);
this.handleChange = this.handleChange.bind(this);
this.handleClick = this.handleClick.bind(this)
}
handleChange(e) {
this.setState({
[e.target.name]: e.target.value,
});
}
handleClick(){
console.log('handle click reached')
auth().signOut().then(() => {
console.log('Successfully signed out')
})
.catch(err => {
console.log(err)
})
}
authListener(){
auth().onAuthStateChanged((user)=>{
if(user){
this.setState({
userDetails: user
})
axios.get("https://us-central1-gig-fort.cloudfunctions.net/api/getGigListings")
.then(res=> {
let filteredGigs = res.data
.filter(gig => {
return gig.user === this.state.userDetails.uid
})
this.setState({
filterGigs: filteredGigs
})
})
} else {
this.setState({
userDetails: null
})
console.log('no user signed in')
}
})
}
componentDidMount(){
this.authListener()
}
handleSubmit(e) {
let user = auth().currentUser.uid
const gigData = {
name: this.state.name,
venue: this.state.venue,
time: this.state.time,
date: this.state.date,
genre: this.state.genre,
tickets: this.state.tickets,
price: this.state.price,
user:user
};
auth().currentUser.getIdToken().then(function(token) {
axios("http://localhost:5000/gig-fort/us-central1/api/createGigListing", {
method: "POST",
headers: {
"content-type": "application/json",
"Authorization": "Bearer "+token,
},
data: gigData,
})
})
.then((res) => {
console.log(res);
this.props.history.push('/Homepage')
})
.catch((err) => {
console.error(err);
});
}
render() {
return (
<div className="gig-register">
<Header />
<div className = 'heading-container'>
<h1>Venue Dashboard</h1> <br></br>
{
this.state.userDetails ?
<h3>You are signed in as {this.state.userDetails.email}</h3>
:
null
}
<div className = 'gig-reg-buttons'>
{
this.state.userDetails ?
<Button onClick = {this.handleClick}>Sign out </Button>
:
<Link to = '/' style={{ textDecoration: "none" }}>
<Button>Sign In</Button>
</Link>
}
<Link to="/Homepage" style={{ textDecoration: "none" }}>
<Button>Go to gig listings</Button>
</Link>
</div>
</div>
<div className = 'handle-gigs'>
<div className = 'reg-gig-input'>
<form onSubmit={this.handleSubmit}>
<h3>Register a gig</h3>
<br></br>
<TextField
placeholder="Event name"
defaultValue="Event name"
id="name"
name="name"
onChange={this.handleChange}
/>
<TextField
placeholder="Time"
defaultValue="Time"
type="time"
label="Enter start time"
id="time"
name="time"
InputLabelProps={{
shrink: true,
}}
inputProps={{
step: 300, // 5 min
}}
onChange={this.handleChange}
/>
<TextField
id="date"
label="Select date"
type="date"
defaultValue="2017-05-24"
InputLabelProps={{
shrink: true,
}}
onChange={(e) => {
this.setState({ date: e.target.value });
}}
/>
<TextField
placeholder="Genre"
defaultValue="Genre"
id="genre"
name="genre"
onChange={this.handleChange}
/>
<TextField
placeholder="Tickets"
defaultValue="Tickets"
id="tickets"
name="tickets"
onChange={this.handleChange}
/>
<TextField
placeholder="Price"
defaultValue="Price"
id="price"
name="price"
onChange={this.handleChange}
/>
<Button type="submit">Submit</Button>
</form>
</div>
<div className = 'manage-gigs'>
<h3 className = 'manage-gig'>Manage your gigs</h3>
<br></br>
{ this.state.userDetails ?
<UniqueVenueListing gigList = {this.state.filterGigs}/>
:
<h2>no gigs to show</h2>
}
</div>
</div>
</div>
);
}
}
export default GigRegister
Can anyone suggest a solution so that the GigRegister component loads properly on the first time? I should mention that GigRegister is directed to from the login component, upon successful login.
You are trying to do multiple dependent state changes in one batch
This part needs to be split in 2
authListener(){
auth().onAuthStateChanged((user)=>{
if(user){
this.setState({
userDetails: user
})
axios.get("https://us-central1-gig-fort.cloudfunctions.net/api/getGigListings")
.then(res=> {
let filteredGigs = res.data
.filter(gig => {
return gig.user === this.state.userDetails.uid
})
this.setState({
filterGigs: filteredGigs
})
})
} else {
this.setState({
userDetails: null
})
console.log('no user signed in')
}
})
}
Since you set userDetails and then try to use it in one "batch". Put the data request in a componentDidUpdate or useEffect. I recommend only using functional components with hooks.
React.useEffect(() => {
if (state.userDetails) {
/* data request */
}
}, [userDetails])
But since you use a class you need component did update.
componentDidUpdate() {
if (this.state.userDetails && !this.state.filterGigs) {
/* data request */
}
}
This way your component responds to getting data when it has rerendered with its new props.
I got list of images from an API, but none of them simply don't show up inside my app, it just hits the alt.. <img scr={this.state.randomImg} alt="Meme"></img> What-I-got-on-screen-after-hitting-"generete"-button-few-times.jpg although if I just paste same scr in inside the img in regular html file it renders perfectly
import React, { Component } from 'react';
class MemeGenerator extends Component {
constructor() {
super();
this.state = {
randomImg: "https://i.imgflip.com/1ur9b0.jpg",
question: "",
punchline: "",
allMemes: []
}
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.getRandomInt = this.getRandomInt.bind(this);
this.componentDidMount = this.componentDidMount.bind(this);
}
getRandomInt(max) {
return Math.floor(Math.random() * Math.floor(max));
}
componentDidMount() {
const imgFlip = "https://api.imgflip.com/get_memes";
fetch(imgFlip)
.then(response => response.json())
.then(response => {
const memes = response.data.memes;
this.setState(
{
allMemes: memes
}
)
this.setState({
randomImg: memes[this.getRandomInt(memes.length)].url
})
console.log(this.state.randomImg);
})
}
handleChange(event) {
const { name, value } = event.target;
this.setState(
{
[name]: value
}
)
}
handleSubmit(event) {
const number = this.getRandomInt(this.state.allMemes.length);
this.setState({
randomImg: this.state.allMemes[number].url
});
event.preventDefault();
console.log(this.state.randomImg);
}
render() {
return (
<main>
<form className='make-meme'>
<input type="text" name="question" value={this.state.question} onChange={this.handleChange} />
<input type="text" name="punchline" value={this.state.punchline} onChange={this.handleChange} />
<button type="submit" onClick={this.handleSubmit}>Genenerate</button>
</form>
<div className="imgWrapper">
<img scr={this.state.randomImg} alt="Meme"></img>
<h2 className="meme-text question">{this.state.question}</h2>
<h2 className="meme-text punchline">{this.state.punchline}</h2>
</div>
</main>
);
}
}
export default MemeGenerator;
My first question don't judge please
scr property of your image should be src
For Example:
you should have
<img src={this.state.randomImg} alt="Meme"></img>
I have written a crud application and it works great!
I have successfully implemented when people click on ADD NEW button form will be visible
Now i am facing challange to hide form when people click on SAVE button, coz, the SAVE another component.
Here you go for my Form.js File:
import React, { Fragment } from "react"
import { connect } from 'react-redux'
const axios = require('axios');
class Form extends React.Component {
constructor(props) {
super(props);
this.state = {
id: this.props.selectedData.id,
name: this.props.selectedData.name,
age: this.props.selectedData.age,
};
this.onHandleChange = this.onHandleChange.bind(this);
this.submit = this.submit.bind(this);
}
submit(event) {
const data = {
name: this.state.name,
age: this.state.age,
email: this.state.email
};
if (this.props.isEdit) {
data.id = this.props.selectedData.id;
axios.put('http://127.0.0.1:8000/api/v1/employee/' + data.id + '/', data)
.then((response) => {
this.props.dispatch({ type: 'EDIT_POST', response });
});
} else {
// generate id here for new emplyoee
axios.post('http://127.0.0.1:8000/api/v1/employee/', data)
.then((response) => {
this.props.dispatch({ type: 'ADD_POST', response });
});
}
}
onHandleChange(event) {
this.setState({
[event.target.name]: event.target.value
});
}
componentDidUpdate(prevProps) {
if (prevProps.selectedData.age !== this.props.selectedData.age) { //Check on email, because email is unique
this.setState({ name: this.props.selectedData.name, age: this.props.selectedData.age })
}
}
render() {
return (
<form>
<div className="form-group">
<input onChange={(event) => this.onHandleChange(event)} value={this.state.name} name="name" type="text" />
</div>
<div className="form-group">
<input onChange={(event) => this.onHandleChange(event)} value={this.state.age} name="age" type="number" />
</div>
<button onClick={(event) => this.submit(event)} type="button">
{this.props.isEdit ? 'Update' : 'SAVE'}
</button>
</form>
);
}
}
export default connect(null)(Form);
And this is my Home.js file:
import React from "react"
import Table from "../components/table"
import Form from '../components/form'
class Home extends React.Component {
constructor(props) {
super(props);
this.state = {
selectedData: {name: '', age: ''},
isEdit: false,
isFormVisible: false,
};
}
selectedData = (item) => {
this.setState({selectedData: item,isEdit:true, isFormVisible: true})
}
render() {
return (
<React.Fragment>
{this.state.isFormVisible && <div>
<Form selectedData={this.state.selectedData} isEdit={this.state.isEdit}/>
</div>}
{!this.state.isFormVisible &&
<button onClick={() => this.setState({isFormVisible: true})}>ADD NEW</button>}
<table>
<Table selectedData={this.selectedData} />
</table>
</React.Fragment>
);
}
}
export default Home;
Everything is working fine, only issue is hiding the form when i click on SAVE button.
Can anyone help to hide the form clicing on SAVE button?
Inside your Home.js, create a function that does the state change for you and pass it down as a prop to the Form Component.
Home.js
changeFormState = () => {
this.setState({ isFormVisible: !isFormVisible });
}
<Form
changeFormState={this.changeFormState}
selectedData={this.state.selectedData}
isEdit={this.state.isEdit}
/>
Form.js
<button
onClick={(event) => { this.props.isEdit ? this.submit(event) :
this.props.changeFormState() }} type="button"
>
{this.props.isEdit ? 'Update' : 'SAVE'}
</button>
JS Update
submit(event) {
const data = {
name: this.state.name,
age: this.state.age,
email: this.state.email
};
if (this.props.isEdit) {
data.id = this.props.selectedData.id;
axios.put('http://127.0.0.1:8000/api/v1/employee/' + data.id + '/', data)
.then((response) => {
// Fire an event
this.props.onSave && this.props.onSave();
this.props.dispatch({ type: 'EDIT_POST', response });
});
} else {
// generate id here for new emplyoee
axios.post('http://127.0.0.1:8000/api/v1/employee/', data)
.then((response) => {
// Fire an event
this.props.onSave && this.props.onSave();
this.props.dispatch({ type: 'ADD_POST', response });
});
}
}
hideForm = () => { this.setState({ isFormVisible: false }); }
JSX Update
<Form
selectedData={this.state.selectedData}
isEdit={this.state.isEdit}
onSave={this.hideForm}
/>
I'm trying to create a change password page in react and i'm getting typeError: cannot read property 'users' of null. The code works for other form pages(where i'm doing PUT and CREATE) but not this one
I tried binding the submit handler to the this keyword but that didn't work.
Also tried binding the handlePasswordChange to the this keyword
./formchange
import React from "react";
import { Link } from "react-router-dom";
var createReactClass = require("create-react-class");
var FormChange = createReactClass({
//setting initial state
getInitialState() {
return {
password: {}
};
},
handlePasswordChange(e) {
this.setState({
password: e.target.value
});
},
handleSubmit(e) {
e.preventDefault();
this.props.onSubmit(this.state);
this.props.history.push("/");
},
render() {
return (
<form
name="categories_post"
className="form-horizontal"
onSubmit={this.handleSubmit}
>
<div id="change_password">
<div className="form-group">
<label
className="col-sm-2 control-label required"
htmlFor="password"
>
Password
</label>
<div className="col-sm-10">
<input
type="text"
value={this.state.password}
onChange={this.handlePasswordChange}
id="password"
className="form-control"
/>
</div>
</div>
<button
type="submit"
id="formChangeSubmit"
className="btn btn-default"
>
Submit
</button>
</div>
</form>
);
}
});
export default FormChange;
./passwordupdate
import React from "react";
import { updateUsers, fetchUsers } from "./actions/appactions";
import FormChange from "./formchange";
var createReactClass = require("create-react-class");
const Update = createReactClass({
getIntitialState() {
return {
users: {}
};
},
componentWillReceiveProps(props) {
this.setState(props);
},
componentDidMount() {
fetchUsers(this.props.match.params.usersId)
.then(data => {
this.setState(state => {
state.users = data;
return state;
});
})
.catch(err => {
console.error("error", err);
});
},
handleSubmit(data) {
updateUsers(this.state.users.id, data);
},
render() {
return (
<div>
<FormChange
onSubmit={this.handleSubmit.bind}
password={this.state.users.password}
/>
</div>
);
}
});
export default Update;
//fetchusers function
export function fetchUsers(id) {
return fetch("https://localhost:44341/api/users/" + id, {
method: "GET",
mode: "cors"
})
.then(res => res.json())
.catch(err => err);
}
<FormChange
onSubmit={this.handleSubmit.bind(this)}
password={this.state.users.password}
/>
make this change and check
I'm not sure but you have data in handleSubmit as parameter but you don't pass it.
try this
You can call function like this:
handleSubmit=(data)=> {
updateUsers(this.state.users.id, data);
},
and call it
onSubmit={(data)=> this.handleSubmit(data)}
The problem was in ComponentDidMount(). The state was always null, had to change it to this
componentDidMount() {
fetchTheUsers(this.props.match.params.usersId)
.then(data => {
this.setState({
users: data
});
})
I did it that way initially because that's how it worked for my other update files. Hope this is useful to someone else.