I have a dashboard that shows the future and past lessons. Future lessons refresh every minute. Generally, the state doesn't change. I have a feedback form at the pastLessons.js file. When I fill the form data and
"Future lessons component" (futureLessons.js) refresh all form data cleared.
Dashboard.js
import React, { Fragment, useEffect } from 'react';
import { connect } from 'react-redux';
import FutureLessons from './futureLessons';
import PastLessons from './pastLessons';
import { getCurrentProfile } from '../../actions/profile';
const Dashboard = ({
getCurrentProfile,
auth: { user },
profile: { profile, loading },
}) => {
useEffect(
() => {
getCurrentProfile();
},
[getCurrentProfile]
);
return (
<Fragment>
<h1 className='large text-primary'>Dashboard</h1>
<p className='lead'>
<i className='fas fa-user' /> Welcome {user && user.name}
</p>
<Fragment>
<FutureLessons />
<PastLessons />
</Fragment>
</Fragment>
);
};
const mapStateToProps = (state) => ({
auth: state.auth,
profile: state.profile,
});
export default connect(mapStateToProps, { getCurrentProfile })(Dashboard);
pastlessons.js
import React, { useEffect } from 'react'
import { connect } from 'react-redux'
import DataTable, { memoize } from 'react-data-table-component'
import { Tab } from 'semantic-ui-react'
import {
getPastSlots,
deleteStudentSlot,
getPastSlotsInitial,
getFeedbacks
} from '../../actions/index'
import moment from 'moment'
import FeedBackTeacher from './feedBackTeacher'
import { Link } from 'react-router-dom'
const PastLessons = ({
getPastSlotsInitial,
studentSlot,
getPastSlots,
getFeedbacks,
user,
feedbacks
}) => {
useEffect(() => {
(async function () {
try {
await getPastSlotsInitial()
await getFeedbacks()
} catch (e) {
console.error(e)
}
})()
}, [getPastSlotsInitial, getFeedbacks])
const columns = memoize(clickHandler => [
...
])
const ExpanableComponent = ({ data }) => (
<div className='box-sh-2-wh p-1 m'>
{data.lesson && (
<Tab
className='text-left'
panes={[
{
menuItem: 'Teacher\'s Feedback',
render: () => (
<Tab.Pane>
{feedbacks.find(fb => fb._id === data._id)
.evaluatedByTeacher ? (
<div className='break-word'>
<FeedBackTeacher
data={feedbacks.find(fb => fb._id === data._id)}
/>
</div>
) : null}
</Tab.Pane>
)
}
]}
/>
</div>
)
return (
<div className='box-sh-1-wh mt-3'>
{(studentSlot &&
studentSlot.pastSlots &&
studentSlot.pastSlots.length > 0) && (feedbacks && feedbacks.length>0) ? (
<DataTable
title='Previous Lessons'
data={studentSlot.pastSlots}
columns={columns()}
pagination
dense
highlightOnHover
expandableRows
expandableRowsComponent={<ExpanableComponent />}
expandOnRowClicked
/>
) : null}
</div>
)
}
const mapStateToProps = state => ({
studentSlot: state.studentSlot,
feedbacks: state.studentSlot.feedbacks,
user: state.auth.user
})
export default connect(mapStateToProps, {
getPastSlots,
deleteStudentSlot,
getPastSlotsInitial,
getFeedbacks
})(PastLessons)
FeedbackTeacher.js
import React, { useEffect, useState } from 'react'
import { connect } from 'react-redux'
import { createTeacherFeedBack } from '../../actions/index'
import { withRouter } from 'react-router-dom'
import { setAlert } from '../../actions/alert'
const FeedBackTeacher = ({ data, createTeacherFeedBack }) => {
const [formData, setFormData] = useState({
pronounciation: '',
vocabulary: '',
grammarCorrection: '',
recommendation: '',
teacherNote: '',
})
useEffect(() => {
data &&
setFormData({
pronounciation: !data.pronounciation ? '' : data && data.pronounciation,
vocabulary: !data.vocabulary ? '' : data && data.vocabulary,
grammarCorrection: !data.grammarCorrection
? ''
: data && data.grammarCorrection,
recommendation: !data.recommendation ? '' : data && data.recommendation,
teacherNote: !data.teacherNote ? '' : data && data.teacherNote,
// teacher_name: !data.teacher_name ? '' : data.teacher_name
})
}, [data])
const {
pronounciation,
vocabulary,
grammarCorrection,
recommendation,
teacherNote
} = formData
const onChange = (e, name) => {
setFormData({ ...formData, [e.target.name]: e.target.value })
}
const onSubmit = e => {
e.preventDefault()
const id = data._id
setFormData({ ...formData, user_name: data.student_name })
createTeacherFeedBack(formData, id, true)
setAlert('Thank you for your Feedback', 'success')
}
return (
<div>
<form className='form text-left evaluation' onSubmit={e => onSubmit(e)}>
<div>
<div className='form-group colspan-2'>
<textarea
placeholder='Pronounciation'
name='pronounciation'
value={pronounciation}
onChange={e => onChange(e)}
/>
<small className='form-text'>Pronounciation</small>
</div>
<div className='form-group colspan-2'>
<textarea
placeholder='Vocabulary'
name='vocabulary'
value={vocabulary}
onChange={e => onChange(e)}
/>
<small className='form-text'>Vocabulary</small>
</div>
<div className='form-group colspan-2'>
<textarea
placeholder='Grammar Correction'
name='grammarCorrection'
value={grammarCorrection}
onChange={e => onChange(e)}
/>
<small className='form-text'>Grammar Correction</small>
</div>
<div className='form-group colspan-2'>
<textarea
placeholder='Recommendation'
name='recommendation'
value={recommendation}
onChange={e => onChange(e)}
/>
<small className='form-text'>Recommendation</small>
</div>
<div className='form-group colspan-2'>
<textarea
placeholder='Teacher Note'
name='teacherNote'
value={teacherNote}
onChange={e => onChange(e)}
/>
<small className='form-text'>Other Notes</small>
</div>
<div></div>
<input
type='submit'
value='Submit'
className='btn btn-primary my-1'
/>
</div>
</form>
</div>
)
}
export default connect(null, { createTeacherFeedBack, setAlert })(
withRouter(FeedBackTeacher)
)
futureLessons.js similar to pastLesson.js
futureLessons.js
const FutureLessons = ({
studentSlot,
getFutureSlots,
deleteStudentSlot,
user,
}) => {
useEffect(() => {
getFutureSlots()
}, [getFutureSlots])
useEffect(() => {
const interval = setInterval(() => {
getFutureSlots();
}, 60000);
return () => clearInterval(interval);
}, [getFutureSlots]);
I tried to use redux-form but nothing changed. "pastLesson.js" file state doesn't change. Only futureLessons.js refreshes every minute. Redux dev tool image like this:
Redux dev tool image
States are equal but my form all data cleared.
Related
I am faced with an issue where when I submit a form, whether it was successful or not, the whole of the form field resets. so I am assuming that is because the component is rerendering.
I want when I submit a form, whether the network request was successful or not, I want it to still maintain the field contents
below is how the entire code looks like:
import { Formik, FieldArray } from 'formik';
import * as Yup from 'yup';
import React, { useEffect } from 'react';
import * as Style from './create-lesson-form.styles';
import { ReactComponent as AddNewIcon } from '../../assets/add-new.svg';
import { ReactComponent as RemoveRecent } from '../../assets/remove-recent.svg';
import CustomButton from '../custom-button/custom-button.component';
import SimpleCheckBox from '../field-inputs/simple-checkbox/simple-checkbox.component';
import { createALessonNote } from '../../redux/lesson_note/lesson_note.actions';
import { LessonNotePayload } from '../../redux/lesson_note/lesson_note.types';
import { connect } from 'react-redux';
import { CreateLessonPropType } from './create-lesson-form.types';
import ToastAlert from '../toast/toast.components';
import { createStructuredSelector } from 'reselect';
import {
selectLessonCreationIsSuccess,
selectLessonNoteError,
selectLessonNoteSuccess,
} from '../../redux/lesson_note/lesson_note.selector';
import { selectSubjects } from '../../redux/subject/subject.selector';
import { fetchSubjectAction } from '../../redux/subject/subject.action';
import { fetchLevelAction } from '../../redux/level/level.action';
import { selectLevels } from '../../redux/level/level.selectors';
const CreateLessonForm: React.FC<CreateLessonPropType> = ({
createLessonNote,
fetchSubjects,
fetchLevels,
lesson_note_error,
lesson_note_success,
isLessonCreated,
subjects,
levels,
}) => {
const handleAddStepsField = (values: any, setValues: any) => {
const steps = [...values.steps];
steps.push('');
setValues({ ...values, steps });
};
const handleAddParagraphField = (values: any, setValues: any) => {
const paragraphs = [...values.paragraphs];
paragraphs.push('');
setValues({ ...values, paragraphs });
};
const handleDeleteParagraphFields = (values: any, setValues: any) => {
const paragraphs = [...values.paragraphs];
paragraphs.pop();
setValues({ ...values, paragraphs });
};
const handleDeleteStepsFields = (values: any, setValues: any) => {
const steps = [...values.steps];
steps.pop();
setValues({ ...values, steps });
};
const fetchFormValues = async (values: any) => {
const lessonPayload: LessonNotePayload = {
class_id: values.class,
subject_id: values.subject,
topic: values.topic,
is_published: values.is_published,
lesson_body: values.paragraphs,
lesson_plan: values.steps,
};
await createLessonNote(lessonPayload);
};
useEffect(() => {
fetchSubjects();
fetchLevels();
}, []);
return (
<Style.CreateLessonNoteContainer>
{lesson_note_error.length ? <ToastAlert message={lesson_note_error} type="failure" /> : null}
{isLessonCreated ? <ToastAlert message={lesson_note_success} type="success" /> : null}
<Formik
/**
*Declare field initial values
*/
initialValues={{
topic: '',
subject: '',
class: '',
is_published: false,
date_of_delivery: '',
paragraphs: [],
steps: [],
}}
/**
* validate form on client side
*/
validationSchema={Yup.object({
topic: Yup.string().required(),
subject: Yup.string().required(),
class: Yup.number().required(),
date_of_delivery: Yup.date().required(),
paragraphs: Yup.array().of(Yup.string().required()),
steps: Yup.array().of(Yup.string().required()),
})}
/**
* listen to user submit action
*/
onSubmit={async (values, { setSubmitting, resetForm }) => {
alert(values);
console.log(values);
await fetchFormValues(values);
if (isLessonCreated) {
resetForm();
console.log('reset form');
}
setSubmitting(false);
}}
>
{({ values, setValues }) => (
<>
<Style.FormTag>
<Style.LessonBodyFooter>
<Style.LessonHeadInput>
<Style.LessonParagraphHeader>
<h3>Lesson Header</h3>
</Style.LessonParagraphHeader>
<Style.CustomTextInput label="Topic" name="topic" type="text" />
<Style.CustomSelectDropdown label="Subject" name="subject">
<option value={''} disabled selected>
select subject
</option>
{subjects.map((subject) => {
return (
<option key={subject.id} value={subject.id}>
{subject.title}
</option>
);
})}
</Style.CustomSelectDropdown>
<Style.CustomSelectDropdown label="Level" name="class">
<option value={''} disabled selected>
select level
</option>
{levels.map((level) => {
return (
<option key={level.id} value={level.id}>
{level.title}
</option>
);
})}
</Style.CustomSelectDropdown>
<Style.CustomTextInput
label="Date of delivery"
name="date_of_delivery"
type="date"
/>
</Style.LessonHeadInput>
<Style.LessonParagraphContainer>
<Style.LessonParagraphHeader>
<h3>Lesson Paragraphs</h3>
<div>
<RemoveRecent
onClick={() => handleDeleteParagraphFields(values, setValues)}
/>
<AddNewIcon onClick={() => handleAddParagraphField(values, setValues)} />
</div>
</Style.LessonParagraphHeader>
<Style.LessonParagraphFieldContainer>
<FieldArray name={'paragraphs'}>
{() =>
values.paragraphs.map((_, index) => {
return (
<Style.LessonParagraphFieldDiv key={index}>
<Style.CustomTextArea
label={`Paragraph ${index + 1}`}
name={`paragraphs.${index}`}
/>
</Style.LessonParagraphFieldDiv>
);
})
}
</FieldArray>
</Style.LessonParagraphFieldContainer>
</Style.LessonParagraphContainer>
<Style.LessonStepContainer>
<Style.LessonParagraphHeader>
<h3>Lesson Steps</h3>
<div>
<RemoveRecent onClick={() => handleDeleteStepsFields(values, setValues)} />
<AddNewIcon onClick={() => handleAddStepsField(values, setValues)} />
</div>
</Style.LessonParagraphHeader>
<Style.LessonParagraphFieldContainer>
<FieldArray name={'steps'}>
{() =>
values.steps.map((_, index) => {
return (
<Style.LessonParagraphFieldDiv key={index}>
<Style.CustomTextArea
label={`Step ${index + 1}`}
name={`steps.${index}`}
/>
</Style.LessonParagraphFieldDiv>
);
})
}
</FieldArray>
</Style.LessonParagraphFieldContainer>
</Style.LessonStepContainer>
</Style.LessonBodyFooter>
<Style.LessonFormFooter>
<SimpleCheckBox name={'is_published'}>Publish Note</SimpleCheckBox>
<CustomButton type="submit">Submit</CustomButton>
</Style.LessonFormFooter>
</Style.FormTag>
</>
)}
</Formik>
</Style.CreateLessonNoteContainer>
);
};
const mapStateToProps = createStructuredSelector({
lesson_note_error: selectLessonNoteError,
isLessonCreated: selectLessonCreationIsSuccess,
lesson_note_success: selectLessonNoteSuccess,
subjects: selectSubjects,
levels: selectLevels,
});
const mapDispatchToProps = (dispatch: any) => {
return {
createLessonNote: ({
class_id,
subject_id,
topic,
is_published,
lesson_body,
lesson_plan,
}: LessonNotePayload) =>
dispatch(
createALessonNote({
class_id,
subject_id,
topic,
is_published,
lesson_body,
lesson_plan,
}),
),
fetchSubjects: () => dispatch(fetchSubjectAction()),
fetchLevels: () => dispatch(fetchLevelAction()),
};
};
export default connect(mapStateToProps, mapDispatchToProps)(CreateLessonForm);
I am trying to conditional render the fields and submit the data.
But on the below code snippet, i am not able to achieve this. Issues are re rendering happens and the values not getting persisting.
Here mostly the problem is i am splitting the schema, so based on the selection of the choice the field renders.
How can i submit the data with proper persisting the validation and values.
What i have tried so far
App.js
import React, { useEffect, useState } from "react";
import "./styles.css";
import Select from "react-select";
import { Controller, useForm } from "react-hook-form";
import { yupResolver } from "#hookform/resolvers";
import { CITIZEN_OPTIONS, validationSchema } from "./util";
import { Resident, NonResident } from "./CitizenDetails";
const Fallback = () => null;
export default function App() {
const [citizenValue, setCitizenValue] = useState(null);
const { register, control, errors, watch, handleSubmit } = useForm({
resolver: yupResolver(validationSchema),
mode: "onBlur",
reValidateMode: "onChange"
});
const watchCitizen = watch("citizen");
useEffect(() => {
setCitizenValue(watchCitizen?.value);
}, [watchCitizen]);
const citizenDetails = {
resident: () => <Resident errors={errors} register={register} />,
non_resident: () => (
<NonResident errors={errors} control={control} register={register} />
)
};
const onSubmit = (data) => {
console.log(data);
};
const SelectedCitizenFields = citizenDetails[citizenValue] || Fallback;
return (
<div className="App">
<Controller
as={Select}
control={control}
name="citizen"
options={CITIZEN_OPTIONS}
></Controller>
<SelectedCitizenFields />
<button onClick={handleSubmit(onSubmit)}>Submit Details</button>
</div>
);
}
CitizenDetails.js
import React, { Fragment, memo } from "react";
import { Controller } from "react-hook-form";
import Select from "react-select";
export const Resident = memo((props) => {
const { errors, register } = props;
return (
<Fragment>
<div className="field-group">
<label>Enter first name</label>
<input ref={register} name="first_name"></input>
{errors?.first_name?.message && (
<span>{errors.first_name.message}</span>
)}
</div>
<div className="field-group">
<label>Enter last name</label>
<input ref={register} name="last_name"></input>
{errors?.last_name?.message && <span>{errors.last_name.message}</span>}
</div>
</Fragment>
);
});
export const NonResident = memo((props) => {
const { errors, register, control } = props;
return (
<Fragment>
<div className="field-group">
<label>Enter passport number</label>
<input ref={register} name="passport_number"></input>
{errors?.passport_number?.message && (
<span>{errors.passport_number.message}</span>
)}
</div>
<div className="field-group">
<label>Choose Country</label>
<Controller as={Select} control={control} name="country" options={[]} />
{errors?.country?.message && <span>{errors.country.message}</span>}
</div>
<div className="field-group">
<label>Choose State</label>
<Controller as={Select} control={control} name="state" options={[]} />
{errors?.state?.message && <span>{errors.state.message}</span>}
</div>
</Fragment>
);
});
util.js
import { object, string, number, lazy } from "yup";
export const CITIZEN_OPTIONS = [
{
label: "Resident",
value: "resident"
},
{
label: "Non-Resident",
value: "non_resident"
}
];
const required = () => "field is required";
const resident_schema = object({
first_name: string().required(required).nullable(),
last_name: string().required(required).nullable()
});
const non_resident_schema = object({
passport_number: string().required(required).nullable(),
country: object().required(required).nullable(),
state: object().required(required).nullable()
});
export const validationSchema = lazy(({ citizen }) => {
return citizen?.value === "resident" ? resident_schema : non_resident_schema;
});
Here is the codesandbox link
I'm trying to require the name and email in my form. I originally had <button> nested within a <Link> and figured out that the <button> worked by itself to allow the input to be required, but that when it's nested within the <Link> it doesn't require it. I then added the link to be within the submitSurvey function and took the <Link> away from the render. It still won't require the input.
Here is my NameEmailComponent.js:
import React, { useState } from "react";
import { NameInput } from "../inputs/NameInput";
import { EmailInput } from "../inputs/EmailInput";
import { useHistory } from "react-router-dom";
export const NameEmailComponent = (props) => {
const [surveyValues, setSurveyValues] = useState({});
const [inlineData, setInlineData] = useState({});
const [question, setQuestion] = useState({});
const history = useHistory();
console.log(props);
const triggerBackendUpdate = () => {
setSurveyValues({});
setQuestion({});
};
const handleSubmit = (event) => {
event.preventDefault();
event.persist();
setSurveyValues(surveyValues);
setQuestion(question);
triggerBackendUpdate();
};
const callback = (name, value) => {
console.log("Form Data: ", name, ": ", value);
inlineData[name] = value;
setInlineData(inlineData);
console.log(inlineData);
};
const handleChange = (event) => {
event.preventDefault();
this.setState({ value: event.target.value });
console.log("Name: ", event.target.value);
};
const submitSurvey = async () => {
try {
await fetch("/api/survey", {
method: "POST",
body: JSON.stringify(inlineData),
headers: {
"Content-Type": "application/json",
},
});
history.push({ pathname: "/survey" });
} catch (err) {
console.log(err);
}
};
const inputs = props.inputs
? props.inputs.filter((inputOption) => inputOption)
: [];
return (
<>
<div id="nameContainer" className="form-group">
<form onSubmit={handleSubmit}>
{inputs.map((data, index) => {
let inputKey = `input-${index}`;
return data.type === "text" ? (
<NameInput
className="form-control my-3"
triggerCallback={callback}
name={data.name}
type={data.type}
placeholder={data.placeholder}
required={true}
onChange={handleChange}
key={inputKey}
/>
) : (
<EmailInput
className="form-control mt-3"
triggerCallback={callback}
name={data.name}
type={data.type}
placeholder={data.placeholder}
required={true}
onChange={handleChange}
key={inputKey}
/>
);
})}
<div className="col-6 mx-auto text-center">
<div className="button">
<button
className="btn btn-primary mt-4 mb-2 mx-5"
type="submit"
onClick={submitSurvey}
>
Begin Survey
</button>
</div>
</div>
</form>
</div>
</>
);
};
Here is my NameInput.js:
import React from "react";
import { useInputChange } from "../Hooks/useInputChangeHook";
import { isTextInput } from "../validators";
export const NameInput = (props) => {
const inputType = isTextInput(props.type) ? props.type : "text";
const { handleChange } = useInputChange(
props.defaultValue,
props.triggerCallback,
inputType
);
const inputProps = {
className: props.className ? props.className : "form-control",
onChange: handleChange,
required: props.required,
question: props.question,
placeholder: props.placeholder,
type: inputType,
options: props.options,
name: props.name ? props.name : `${inputType}_${props.key}`,
};
return (
<>
<div id={props.name}>
<input
{...inputProps}
required={props.required}
value={props.value || ""}
/>
</div>
</>
);
};
After using a form and inserting new data this error show up.
This is my code:
import React from "react";
import { Form, Input, Button } from "antd";
import { connect } from "react-redux";
import axios from "axios";
import hashHistory from './hashHistory';
const FormItem = Form.Item;
class CustomForm extends React.Component {
handleFormSubmit = async (event, requestType, articleID) => {
event.preventDefault();
const postObj = {
title: event.target.elements.title.value,
content: event.target.elements.content.value
}
axios.defaults.xsrfHeaderName = "X-CSRFTOKEN";
axios.defaults.xsrfCookieName = "csrftoken";
axios.defaults.headers = {
"Content-Type": "application/json",
Authorization: `Token ${this.props.token}`,
};
if (requestType === "post") {
await axios.post("http://192.168.196.49:8000/api/create/", postObj)
.then(res => {
if (res.status === 201) {
//this.props.history.push(`/articles/`);
//this.props.hashHistory.push('/');
//hashHistory.push(String('/articles/'))
this.props.history.push({
pathname: "/"
})
}
})
} else if (requestType === "put") {
await axios.put(`http://192.168.196.49:8000/api/${articleID}/update/`, postObj)
.then(res => {
if (res.status === 200) {
//this.props.history.push(`/articles/`);
//this.props.hashHistory.push('/');
//hashHistory.push(String('/articles/'))
this.props.history.push({
pathname: "/"
})
}
})
}
};
render() {
console.log("debug:", this.props)
return (
<div>
<Form
onSubmit={event =>
this.handleFormSubmit(
event,
this.props.requestType,
this.props.articleID
)
}
>
<FormItem label="TÃtulo">
<Input name="title" placeholder="Put a title here" />
</FormItem>
<FormItem label="Comentario">
<Input name="content" placeholder="Enter some content ..." />
</FormItem>
<FormItem>
<Button type="primary" htmlType="submit">
{this.props.btnText}
</Button>
</FormItem>
</Form>
</div>
);
}
}
const mapStateToProps = state => {
return {
token: state.token
};
};
export default connect(mapStateToProps)(CustomForm);
Routes
<Route exact path="/articles/" component={ArticleList} />{" "}
<Route exact path="/articles/:articleID/" component={ArticleDetail} />{" "}
Error message:
TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type undefined
The data is storing correcty to the database, but just after submiting there is this error.
My original code was using history.push but tried hashHistory.push.
I am using redux in the proyect.
Verision using:
react-router 5.1.2
history 4.9.0
Try make a module hashHistory:
// hashHistory.js
import { createHashHistory } from 'history'; // worked for the OP
export default createHashHistory({});
And use it:
const history = createHashHistory();
// ....
// **EDIT** This should work
history.push("/articles/")
You can use withRouter to push history in props.
import { withRouter } from 'react-router';
const SpecialButton = withRouter(({ history, path, text }) => {
return (
<Button
onClick={() => { history.push(path); }}
>
{text}
</Button>
)
});
This was the solution that works (may be is not the best one...)
code:
import React from "react";
import { Form, Input, Button } from "antd";
import { connect } from "react-redux";
import axios from "axios";
import { createHashHistory } from 'history'
const FormItem = Form.Item;
class CustomForm extends React.Component {
handleFormSubmit = async (event, requestType, articleID) => {
event.preventDefault();
const postObj = {
title: event.target.elements.title.value,
content: event.target.elements.content.value
}
axios.defaults.xsrfHeaderName = "X-CSRFTOKEN";
axios.defaults.xsrfCookieName = "csrftoken";
axios.defaults.headers = {
"Content-Type": "application/json",
Authorization: `Token ${this.props.token}`,
};
const history = createHashHistory();
if (requestType === "post") {
console.log("debug_1.1_Form_post_history: ", history )
await axios.post("http://192.168.196.49:8000/api/create/", postObj)
.then(res => {
if (res.status === 201) {
history.push("/articles/")
}
})
} else if (requestType === "put") {
console.log("debug_1.2_Form_put_history: ", history )
await axios.put(`http://192.168.196.49:8000/api/${articleID}/update/`, postObj)
.then(res => {
if (res.status === 200) {
console.log("debug_1.3_Form_put_this.props: ", this.props)
history.push("/articles/");
}
})
}
};
render() {
return (
<div>
<Form
onSubmit={event =>
this.handleFormSubmit(
event,
this.props.requestType,
this.props.articleID
)
}
>
<FormItem label="Title">
<Input name="title" placeholder="Put a title here" />
</FormItem>
<FormItem label="Content">
<Input name="content" placeholder="Enter some content ..." />
</FormItem>
<FormItem>
<Button type="primary" htmlType="submit">
{this.props.btnText}
</Button>
</FormItem>
</Form>
</div>
);
}
}
const mapStateToProps = state => {
return {
token: state.token
};
};
export default connect(mapStateToProps)(CustomForm);
I am getting the error
Error: Function components cannot have refs. Did you mean to use
React.forwardRef()?
And if you check my code it is correct. I am also passing even and it says
Line 91: Unexpected use of 'event' no-restricted-globals
If I am doing something wrong I do not know. According to my research I found that there is some version issue maybe or not. I am using the latest version of create react app
import React, { Component } from 'react';
import { AuthUserContext } from '../Session';
import { withFirebase } from '../Firebase';
import NewsList from './NewsList';
import { ValidatorForm, TextValidator } from 'react-material-ui-form-validator';
import { Container, Card, CardContent, Button } from '#material-ui/core';
import Form from 'react-bootstrap/Form';
class News extends Component {
constructor(props) {
super(props);
this.state = {
newsTitle: '',
newsDescription: '',
news: [],
limit: 5,
loading: false,
submitted: false,
error: null,
};
}
componentDidMount() {
this.onListenForNews();
}
onListenForNews = () => {
this.setState({ loading: true });
this.props.firebase
.news()
.orderByChild('createdAt')
.limitToLast(this.state.limit)
.on('value', snapshot => {
const newsObject = snapshot.val();
if (newsObject) {
const newsLis = Object.keys(newsObject).map(key => ({
...newsObject[key],
uid: key,
}));
this.setState({
news: newsLis,
loading: false,
});
} else {
this.setState({ news: null, loading: false });
}
});
};
componentWillUnmount() {
this.props.firebase.news().off();
}
handleChange = (event) => {
this.setState({ [event.target.name]: event.target.value });
};
onCreateNews = (event, authUser) => {
this.props.firebase.news().push({
newsTitle: this.state.newsTitle,
newsDescription: this.state.newsDescription,
userId: authUser.uid,
createdAt: this.props.firebase.serverValue.TIMESTAMP,
});
this.setState({
newsTitle: '',
newsDescription: '',
error: null,
submitted: true,
});
event.preventDefault();
};
onEditNews = (news, newsTitle, newsDescription) => {
this.props.firebase.news(news.uid).set({
...news,
newsTitle,
newsDescription,
editedAt: this.props.firebase.serverValue.TIMESTAMP,
});
};
onRemoveNews = uid => {
this.props.firebase.news(uid).remove();
};
onNextPage = () => {
this.setState(
state => ({ limit: state.limit + 5 }),
this.onListenForNews,
);
};
render() {
const { users } = this.props;
const { newsTitle, newsDescription, news, loading, submitted, error } = this.state;
return (
<AuthUserContext.Consumer>
{authUser => (
<div>
{!loading && news && (
<button type="button" onClick={this.onNextPage}>
More
</button>
)}
{loading && <div>Loading ...</div>}
{news && (
<NewsList
news={news.map(news => ({
...news,
user: users
? users[news.userId]
: { userId: news.userId },
}))}
onEditNews={this.onEditNews}
onRemoveNews={this.onRemoveNews}
/>
)}
{!news && <div>There are no messages ...</div>}
<Container maxWidth="lg">
<ValidatorForm
ref="form"
onSubmit={event =>
this.onCreateNews(event, authUser)
}
>
<div>
{error && (
<div className="alert alert-danger" role="alert">
{error.message}
</div>
)}
<Card>
<CardContent>
<Form.Group>
<TextValidator
label="News Title"
onChange={this.handleChange}
name="newsTitle"
type="text"
value={newsTitle}
variant="outlined"
fullWidth={true}
validators={['required']}
errorMessages={['New title field is required', 'News title is not valid']}
/>
</Form.Group>
<Form.Group>
<TextValidator
label="Description"
onChange={this.handleChange}
name="newsDescription"
type="text"
value={newsDescription}
variant="outlined"
fullWidth={true}
validators={['required']}
errorMessages={['Description field is required']}
/>
</Form.Group>
<Form.Group>
<Button
color="primary"
variant="contained"
type="submit"
fullWidth={true}
size="large"
disabled={submitted}
>
{
(submitted && 'Signing In - Redirecting')
|| (!submitted && 'Sign In')
}
</Button>
</Form.Group>
</CardContent>
</Card>
</div>
</ValidatorForm>
</Container>
</div>
)}
</AuthUserContext.Consumer>
);
}
}
export default withFirebase(News);