I'm learning to use react-redux, so sorry if I'm doing confusing!
I'm trying to create a form and insert data into the db.
Then I have created 2 page, one for the form and another one.
RequestForm
handleChange = (e) => {
let meeting = this.state.meeting;
meeting[e.target.name] = e.target.value;
this.setState({ meeting });
};
handleSubmit(event) {
event.preventDefault();
console.log(this.state.meeting);
this.props.addMeeting(this.state)
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<div>
<label>Motivation:</label>
<input
type="text"
name="motivation"
onChange={(event) => this.handleChange(event)}
/>
</div>
<div>
<label>Date:</label>
<input
type="date"
name="date"
onChange={(event) => this.handleChange(event)}
/>
</div>
MeetingRequest.js
import RequestForm from './RequestForm';
import { connect } from 'react-redux';
import {addMeeting} from '../Redux/actions';
class MeetingRequest extends Component {
render() {
const addMeeting = this.props
return (
<div>
<h2>Request Meeting</h2>
<RequestForm
addMeeting={addMeeting}
/>
</div>
);
}
}
function mapDispatchToProps(dispatch) {
return {
addMeeting: (meeting) => dispatch(addMeeting(meeting)),
};
}
export default connect(null, mapDispatchToProps)(MeetingRequest);
EDIT. Thank you to the comments the firt error is resolved, now I have a 500 problem. Could it be a problem about the Actions.js??
And also in your opinion is right how I'm trying to do??
Thank you
Change:
-const addMeeting = this.props
+const { addMeeting } = this.props
in MeetingRequest.js
Regarding your 500 error on API, it may be because you're sending JSON while setting multipart/form-data. Inspect using Network tab in dev tools.
If your backend need multipart/form-data you have to convert your state.meeting object to FormData
Related
I am trying to post new information about a cow to my cow API, however, everytime i hit the submit button on my frontend, it seems to be sending an empty object rather than the name of the cow, description of the cow, and image of the cow (via url). What is causing it to send an empty object versus my desired data?
Here is the frontend code:
import React, { useEffect, useState } from 'react';
import axios from 'axios';
import './App.css';
const baseUrl = "http://localhost:3001/api/cows"
function Display({setNameOfCow, setImageOfCow, setDescriptionOfCow, nameOfCow, imageOfCow, descriptionOfCow}) {
axios.get(baseUrl)
.then(res => res.data)
.then(res => {
setNameOfCow(res.name)
setImageOfCow(res.image)
setDescriptionOfCow(res.description)
})
return (
<div>
<p>{nameOfCow}</p>
<img src={imageOfCow}/><p>{descriptionOfCow}</p>
</div>
)
}
function Input({setNameOfCow, setImageOfCow, setDescriptionOfCow, nameOfCow, imageOfCow, descriptionOfCow}) {
function handleSubmit(e) {
e.preventDefault()
let newObject = {
name: nameOfCow,
description: descriptionOfCow,
image: imageOfCow
}
axios.post(baseUrl, newObject)
}
return (
<div>
<form>
<label htmlFor="name">name: </label>
<input type="text" id="name" onChange={(e) => {
const eTarget = e.target.value
setNameOfCow(eTarget)}}/><br></br>
<label htmlFor="description">description: </label>
<input type="text" id="description" onChange={(e) => {
const eTargetDesc = e.target.value
setDescriptionOfCow(eTargetDesc)}}/><br></br>
<label htmlFor="image">image url: </label>
<input type='text' id="image" onChange={(e) => {
const eTargetImage = e.target.value
setImageOfCow(eTargetImage)}}/><br></br>
<button type="submit" onSubmit={handleSubmit}>Add a cow!</button>
</form>
</div>
)
}
function App() {
const [nameOfCow, setNameOfCow] = useState('')
const [descriptionOfCow, setDescriptionOfCow] = useState('')
const [imageOfCow, setImageOfCow] = useState('')
return (
<div className="App">
<Input imageOfCow={imageOfCow} setNameOfCow={setNameOfCow} setDescriptionOfCow={setDescriptionOfCow} setImageOfCow={setImageOfCow} />
<Display setNameOfCow={setNameOfCow} setImageOfCow={setImageOfCow} setDescriptionOfCow={setDescriptionOfCow} nameOfCow={nameOfCow} imageOfCow={imageOfCow} descriptionOfCow={descriptionOfCow} />
</div>
);
}
export default App
and here is the image showing the empty objects being posted:
Looking into your Input component props:
function Input({setNameOfCow, setImageOfCow, setDescriptionOfCow, nameOfCow, imageOfCow, descriptionOfCow}) {...
We can see that you missing to pass this props when using this component:
<Input imageOfCow={imageOfCow} setNameOfCow={setNameOfCow} setDescriptionOfCow={setDescriptionOfCow} setImageOfCow={setImageOfCow} />
The correct way to use is something like:
<Input
imageOfCow={imageOfCow}
nameOfCow={nameOfCow}
descriptionOfCow={descriptionOfCow}
setNameOfCow={setNameOfCow}
setDescriptionOfCow={setDescriptionOfCow}
setImageOfCow={setImageOfCow}
/>
Also the correct way to prevent the form default behavior is setting the onSubmit and the handleSubmit at the form attribute (you can remove from the button):
<form onSubmit={handleSubmit}>
Otherwise a very nice change is to put your axios request inside a useEffect hook to prevent your app from making request every time it re-render.
Using something like this the app will make the request only at the first component render.
const getCow = async (baseUrl) => {
const cow = await axios.get(baseUrl);
setNameOfCow(cow.name);
setImageOfCow(cow.image);
setDescriptionOfCow(cow.description);
};
useEffect(() => {
getCow(baseUrl);
}, []);
So Ive been trying for hours to get my api data to render on a screen in reactjs. Ive tried adjusting the map method and playing around with the code but it keeps giving me errors
It doesnt render the info that I am seeing in my console
import React, { Component } from 'react';
import './App.css';
import axios from "axios"
const user_key="cf7a5f91a3331dc1409df6bb967b9689103967f70b5b0f80fef391a4df5a1039"
class App extends Component {
state = {
searching: []
}
getInfo = (e) => {
e.preventDefault();
const info = e.target.elements.search.value;
axios.get(`https://api.mattermark.com/search?key=${user_key}&term=${info}`)
.then((res) => {
console.log(res.data);
this.setState({ searching: res.data})
})
}
handleChange = (e) => {
const entered = e.target.value;
console.log(entered);
}
render() {
console.log(this.state.searching)
return (
<div className="App">
<header className="App-header">
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
</header>
<form onSubmit={this.getInfo}>
<input name="search" onChange={this.handleChange}/>
<button onClick={this.handleSearch}>Search</button>
</form>
{this.state.searching.map((company)=> {
return(
<div>
{company}
</div>
)
})}
{this.state.searching ? <p>Data: {this.state.searching}</p> : "Please type something! "}
</div>
);
}
}
export default App;
My actual result is showing errors
Expected result is to map the various company names from the key "object_name"
PLease see pictures for more info. Thanks!
You should do something like this:
{this.state.searching.map((company)=> {
return(
<div>
Type:{company.object_type}
Name:{company.object_name}
</div>
)
})}
You can't render an object.
UPD: you can use another component for render info about the company and pass data in your mapping, I would do something like this.
const CompanyInfo = ({data}) => (
<div>
<p>{data.object_type}</p>
<p>{data.object_type}</p>
</div>
)
And then:
{this.state.searching.map((company)=> {
return(
<CompanyInfo data={company} />
)
})}
I have a redux form where I have 2 input fields and one select drop-down. I wan to store the values of the inputs to a backend api. I am able to get the values from the inputs and pass it to the server, but for some reason I am not able to correctly get the select drop-down value and pass it to the back-end server. I know I am doing some silly mistake with the state, but I am not able to figure out what is that.My file is as shown below:
import React, { Component } from 'react';
import { Field, reduxForm } from 'redux-form';
import { Link } from 'react-router-dom';
import { connect } from 'react-redux';
import { createPosts } from '../actions/posts_action';
class CreatePost extends Component {
constructor() {
super();
this.state = {
selectValue : 'react'
};
this.handleChange = this.handleChange.bind(this);
this.renderCategory = this.renderCategory.bind(this);
}
renderField(field) {
return(
<div className="title-design">
<label className="label-design"> {field.label} </label>
<input
type="text"
className="title-input"
{...field.input}
/>
<div className="text-help has-danger">
{field.meta.touched ? field.meta.error : ''}
</div>
</div>
);
}
handleChange(e) {
this.setState({selectValue: e.target.value});
console.log(this.state.selectValue);
}
renderCategory(field) {
return(
<div className="title-design">
<label className="label-design">{field.label} </label>
<select
name="categories"
className="title-input"
value={this.state.selectValue}
onChange={this.handleChange} >
<option value="react">React</option>
<option value="redux">Redux</option>
<option value="udacity">Udacity</option>
</select>
{this.state.selectValue}
</div>
);
}
onSubmit(values) {
this.props.createPosts(values, () => {
this.props.history.push('/');
});
}
render() {
const { handleSubmit } = this.props;
return (
<form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
<Field
label="Title for Post"
name="title"
component={this.renderField}
/>
<Field
label="Post Content"
name="body"
component={this.renderField}
/>
<Field
label="Category"
name="category"
component={this.renderCategory}
/>
<button type="submit" className="btn btn-primary">Submit</button>
<Link to="/">
<button className="cancel-button">Cancel</button>
</Link>
</form>
);
}
}
function validate(values) {
const errors = {} ;
if (!values.title) {
errors.title = "Enter a title";
}
if (!values.body) {
errors.body = "Enter some content";
}
return errors;
}
export default reduxForm({
validate : validate, //validate
form : 'CreatePostForm'
})(
connect(null,{ createPosts })(CreatePost)
);
NOTE: Also,I want to generate a unique id for each of the records that is passed to the server so that I can refer to them when I want to retrieve data and display it.Can anyone please guide me how to proceed with both the issues?
setState is not synchronous, it has a callback so you should have something like:
handleChange(e) {
this.setState({selectValue: e.target.value}, () => {
console.log(this.state.selectValue);
});
}
To set the value of the field, you can use change whose signature is:
change(field:String, value:any)
So your handler will just become:
handleChange(e) {
const value = e.target.value;
this.props.change("categories", value);
this.setState({ "selectValue": value }, () => {
console.log(value);
});
}
and in your renderCategory you can remove the value attribute:
...
<select
name="categories"
className="title-input"
onChange={this.handleChange} >
...
To set some random id for every submission, you can find lots of libraries to generate a random one; to assign to the record, use again change method and field "id" will be sent to the server:
this.props.change('id', <random generated Id>)
See this sandbox a rough implementation
I am trying to create a customer details form in react (currently using react-json-form) where I can reuse the values in the inputs to create a saved file that the app can refer to. I have created the form and can output the results but I am unsure how to save the input values for future use or call them back once they are saved.
If anyone has any suggestions or examples of a form that does this then I would be greatly appreciative.
My code is as follows:
import React, { Component } from 'react';
import JSONTree from 'react-json-tree';
import { BasicForm as Form, Nest, createInput } from 'react-json-form';
const Input = createInput()(props => <input type="text" {...props} />);
const UserFields = () => (
<section>
<h3>User</h3>
<div>Name: <Input path="name" /></div>
<div>Email: <Input path="email" /></div>
</section>
);
export default class ExampleForm extends Component {
state = { data: {} };
updateData = data => this.setState({ data });
render() {
return (
<Form onSubmit={this.updateData}>
<Nest path="user">
<UserFields />
</Nest>
<button type="submit">Submit</button>
<JSONTree data={this.state.data} shouldExpandNode={() => true} />
</Form>
);
}
}
A more simple solution would be to use a form, like a semanti-ui-react form, store the information to the state onChange, then convert the info to JSON for storage.
import { Form, Button } from 'semantic-ui-react'
export default class App extends Component {
constructor() {
super()
this.state = {
name: "",
email: ""
}
}
handleChange = (e, {name, value}) => {
console.log(name, value)
this.setState({[name]: value})
}
render() {
return (
<div>
<Form onSubmit={this.sendDataSomewhere}>
<Form.Field>
<Form.Input name="name" value={this.state.name} onChange={this.handleChange}/>
</Form.Field>
<Form.Field>
<Form.Input name="email" value={this.state.email} onChange={this.handleChange}/>
</Form.Field>
<Button type="submit">Submit</Button>
</Form>
</div>
)
}
}
I use a dynamic method of receiving the input from different fields using the name and val attributes. The values captured in state are then accessible by this.state.whatever
Hope this helped
I have a usecase that there is a form which should be controlled one and should have its field be pre-populated so that user can edit the form. For this what i have done is
const mapStateToProps = createStructuredSelector({
myInfo: makeSelectMyInfo(),
errorResponse: makeSelectMyInfoErrorResponse()
});
const mapDispatchToPropes = dispatch => ({
loadMyInfo: () => dispatch(getMyInfo()),
updateMyInfo: (myInfo, token) => dispatch(updateMyInfo(myInfo, token))
});
class ConfirmPropertyByUser extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
user_info: {
contact_fname: "",
contact_lname: "",
agree_terms_condition: false,
}
};
}
componentDidMount() {
this.props.loadMyInfo();
}
componentWillReceiveProps(nextProps) {
if (nextProps.myInfo !== this.props.myInfo) {
console.log("object", Object.values(nextProps.myInfo));
this.setState(state => ({
user_info: {
...state.user_info,
contact_fname: nextProps.myInfo.contact_fname,
contact_lname: nextProps.myInfo.contact_lname,
}
}));
}
}
handleChange = e => {
this.setState({
user_info: { ...this.state.user_info, [e.target.name]: e.target.value }
});
};
handleUserTerms = e =>
this.setState({
user_info: {
...this.state.user_info,
agree_terms_condition: e.target.checked
}
});
handleSubmit = e => {
e.preventDefault();
this.props.updateMyInfo(this.state.user_info, this.props.match.params.id);
};
render() {
const { errorResponse } = this.props;
const { user_info } = this.state;
let message;
if (errorResponse && typeof errorResponse === "string") {
message = <Notification message={errorResponse} timeout={5000} />;
}
return (
<div className="container">
{message && message}
<div className="card card-lg">
<h1>Register</h1>
<form onSubmit={this.handleSubmit}>
<div className="form-group">
<label>First Name</label>
<input
type="text"
name="contact_fname"
className="form-control"
value={user_info && user_info.contact_fname}
onChange={this.handleChange}
/>
</div>
<div className="form-group">
<label>Last Name</label>
<input
type="text"
name="contact_lname"
className="form-control"
value={user_info && user_info.contact_lname}
onChange={this.handleChange}
/>
</div>
<div className="form-group">
<input
className="custom-control-input"
type="checkbox"
onChange={this.handleUserTerms}
/>
</div>
<button
className="btn btn-default btn-block btn-lg"
disabled={
!user_info.password || !user_info.agree_terms_condition
}
>
Submit Details
</button>
</fieldset>
</form>
</div>
</div>
);
}
}
export default connect(mapStateToProps, mapDispatchToPropes)(
ConfirmPropertyByUser
);
I am using redux and also updating the internal state. But I have heard somewhere that when using redux its unnecessary to update the internal state. How can i approach the following problem without updating the internal state? Can anyone help me on this, please?
What you're doing appears to be fine. Per the Redux FAQ, there's nothing wrong with using component state in a Redux app. For forms, it's very common to need to have both an "original" set of values and a "work-in-progress" copied set of values, and it's up to you whether the "WIP" values are stored in Redux or in a React component.
For what it's worth, I did show some examples of putting the "WIP" form state into Redux in my blog post Practical Redux, Part 8: Form Draft Data Management, which might be a useful reference. But, overall, your code here looks good - you're correctly copying props to state in the constructor and in componentWillReceiveProps, and the conceptual approach you're following is perfectly fine.
One small stylistic suggestion: I generally recommend that people use the object shorthand syntax for the mapDispatch argument. In your case, it would look like:
const actions = {loadMyInfo : getMyInfo, updateMyInfo : updateMyInfo};
// later
export default connect(mapState, actions)(ConfirmPropertyByUser);