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
Related
What i want is every time user put down there credential and submit the form it will check if the criteria is correct if not State - isSubmit will say falls the user cannot move to other page and if the credential are correct then when the submit button is clicked it will automatically send the user to next page(ToDoTask).
whenever the isSubmit is true and the submit button clicked from this code
import React,{useState,useEffect} from "react";
import './Form.css';
export default function SighIn() {
const [SignInForm , setSignInForm] = useState({
username:"",
email:"",
password:""
})
const [handleErros,setHandleErros] = useState({});
const [isSubmit,setIsSubmit] = useState(false);
const handleChange = (e) => {
const { name, value } = e.target;
setSignInForm({ ...SignInForm, [name]: value });
};
const handleSubmit = (e) => {
e.preventDefault();
setHandleErros(validate(SignInForm))
setIsSubmit(true);
}
useEffect(() => {
console.log(handleErros);
if (Object.keys(handleErros).length === 0 && isSubmit) {
console.log(SignInForm);
}
}, [handleErros]);
//validate email username password -- if else
const validate = (values) => {
const error = {};
const regex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+#[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/
if(!values.username){
error.username = "Username is Required!"
}
if(!values.email){
error.email = "Email is required!";
}else if(!regex.test(values.email)){
error.email = "Email is not in valid fromat!"
}
if(!values.password) {
error.password = "Password is required!"
}else if(values.password.length <= 8){
error.password = "Between 8-20!";
}else if(values.password.length >= 20) {
error.password = "Between 8-20!";
}
return error;
}
return(
<div>
<form className="signForm" onSubmit={handleSubmit}>
<div className="form-content">
<h2>SignIn Form</h2>
<div className="line"></div>
<div className="form">
<div className="field">
<label>Username</label>
<input
type="text"
placeholder="Username"
name='username'
value={SignInForm.username}
onChange={handleChange}
/>
</div>
<p>{handleErros.username}</p>
<div className="line2"></div>
<div className="field">
<label>Email</label>
<input
type='email'
value={SignInForm.email}
name='email'
placeholder="Email"
onChange={handleChange}
/>
</div>
<p>{handleErros.email}</p>
<div className="line2"></div>
<div className="field">
<label>Password</label>
<input
type='password'
value={SignInForm.password}
name='password'
placeholder="Password"
onChange={handleChange}
/>
</div>
<p>{handleErros.password}</p>
<div className="line2"></div>
<button className="Submit-button">Submit</button>
</div>
</div>
</form>
</div>
)
};
the component that i want to show is ToDoTask
here the code
import React from 'react';
import './ToDoTask.css';
import axios from "axios";
class ToDoTask extends React.Component {
state = {
task: "",
taskList: []
}
componentDidMount = () => {
this.getTaskList();
}
getTaskList = () => {
axios
.get('http://localhost:3060/tasks')
.then((response) => response.data)
.then(response2 => {
this.setState({taskList : response2}
)}
)}
onDeleteClick = task_id => {
axios.delete(`http://localhost:3060/deleteTask/${task_id}`)
this.getTaskList();
}
onSubmitClick = () => {
axios.post('http://localhost:3060/addTasks',{
task : this.state.task
});
this.getTaskList()
this.setState({task: ""})
}
render()
{
console.log(this.state.task)
return(
<div>
<h3>Task Maker</h3>
<input placeholder='Task Maker...'className='Header-input' onChange={e => this.setState({
task : e.target.value
})}
value={this.state.task}/>
<button className='Header-button' onClick={
() => this.onSubmitClick()
}>Submit</button>
<hr />
<div className='container'>
{this.state.taskList.map((tasks) =>
<div className="card">
<div className='content'>
<h3 className='task'>{tasks.task}</h3>
</div>
<div className='card-button'>
<button className="button-done">Done</button>
<button className="button-delete" onClick={
() => this.onDeleteClick(tasks.task_id)
}>Delete</button>
</div>
</div>
)};
</div>
</div>
)
}
}
export default ToDoTask;
here's the my app where i am rendering the component
import './App.css';
// import ToDoTask from './Components/ToDoTask';
import SighIn from './Components/SighIn';
function App() {
return (
<div className="App">
<SighIn />
</div>
);
}
export default App;
i tried many thing such as router and other but don't know what to do
Working on a form to store values in redux store using redux-toolkit. Able to log values in the redux dev tools, but the typed values entered in the form are not visible and the validations are not working for the input fields.
userSlice.js
import { createSlice } from '#reduxjs/toolkit';
const initialState = {
name: null,
email: null,
phone: null,
url: null,
message: null
}
export const userSlice = createSlice({
name: 'user',
initialState,
reducers: {
saveUser: (state, action) => {
state.name = action.payload?.name;
state.email = action.payload?.email;
state.phone = action.payload?.phone;
state.url = action.payload?.url;
state.message = action.payload?.message;
}
}
})
export const { saveUser } = userSlice.actions;
export default userSlice.reducer;
store.js
import { configureStore } from '#reduxjs/toolkit';
import userReducer from '../Slice/userSlice';
export const store = configureStore ({
reducer: {
user: userReducer
}
});
Contact.js
import React from 'react';
import ContactForm from '../../Forms/ContactForm';
function Contact() {
return(
<div className="columns">
<ContactForm />
</div>
)
}
export default Contact;
ContactForm.js
import React, { useRef, useState } from 'react';
import { Field, reduxForm } from 'redux-form';
import { useDispatch } from 'react-redux';
import validate from '../Validations/validate';
import renderTextArea from '../Fields/TextAreaInput/renderTextArea';
import renderField from '../Fields/TextInput/renderField';
import './ContactForm.css';
import { saveUser } from '../Slice/userSlice';
function ContactForm() {
const formContainer = useRef(null);
const dispatch = useDispatch();
const [user, setUser] = useState({
name: null,
email: null,
phone: null,
url: null,
message: null
});
const handleChange = e => {
const { name, value } = e.target;
setUser({ ...user, [name]: value });
console.log("user", user)
}
const handleSubmit = e => {
console.log(user, "submit data")
e.preventDefault();
dispatch(saveUser((user)));
}
return (
<div className="container">
<form id="contact" ref={formContainer} onSubmit={handleSubmit}>
<h3>Contact Us</h3>
<fieldset>
<Field name="name" id="name" type="text" placeholder="Your full name" component={renderField} onChange={handleChange} />
</fieldset>
<fieldset>
<Field name="email" id="email" type="email" placeholder="Your email" component={renderField} onChange={handleChange} />
</fieldset>
<fieldset>
<Field name="phone" id="phone" type="text" placeholder="Your phone number" component={renderField} onChange={handleChange} />
</fieldset>
<fieldset>
<Field placeholder="Your Web Site" type="url" name="url" component={renderField} onChange={handleChange} />
</fieldset>
<fieldset>
<Field name="message" component={renderTextArea} id="message" placeholder="Enter your message here..." rows={4} onChange={handleChange} />
</fieldset>
<fieldset>
<button name="submit" type="submit" id="contact-submit">Submit</button>
</fieldset>
</form>
</div>
)
}
export default reduxForm({
form: 'contact',
validate,
})(ContactForm);
validate.js
const validate = val => {
const errors = {}
if (!val.name) {
errors.name = 'Required';
} else if(!/^[a-zA-Z ]+$/.test(val.name)) {
errors.name = 'Invalid Name';
}
if (!val.email) {
errors.email = 'Required';
} else if (!/^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(val.email)) {
errors.email = 'Invalid email address';
}
if (!val.phone) {
errors.phone = 'Required';
} else if (val.phone.length !== 10) {
if(/[^0-9]/.test(val.phone)) {
errors.phone = 'Phone number must be 10 characters'
} else {
errors.phone = 'Invalid phone number'
}
}
if(!val.url) {
val.url = !val.url ? "" : val.url;
}
if (!val.message) {
val.message = !val.message ? "" : val.message;
}
return errors;
}
export default validate;
Screenshots for reference
Form UI after typing inputs
Redux Dev Tools (after clicking on submit)
I am trying to implement my own commenting system.
I already set up the comment form and I receive data in my netlify form submissions.
Then, I use the plugin netlify-plugin-form-submissions, which transforms your netlify form submissions into a json file (in my case in Form submissions data saved: static/comments/approved-comments_submissions.json)
So I am trying to retrieve the submissions data and make them appear as a comment list below my form.
Here is my CommentList Component:
import React, { useReducer } from 'react';
import "./styles.module.css";
class CommentsList extends React.Component {
constructor(props) {
super(props);
this.state = {
commentList: "../../static/comments/approved-comments_submissions.json"
}
}
renderComments() {
return this.state.commentList.map((item, index) => (
<ul>
<li>
<p>{item.data.name} a commenté le {item.created_on}</p>
<p>{item.data.commentaire}</p>
</li>
</ul>
));
}
render() {
return (
<div className="CommentsList">
{this.renderComments()}
</div>
);
}
}
export default CommentsList;
however it does not work, I can't retrieve the data from approved-comments_submissions. I have the following error:
TypeError: this.state.commentList.map is not a function
Besides, how can I render the comments only in the right urlpage? Because comments need to appear only in the right page
Here is an exemple of the data submission json file
[{"number":19,"title":null,"email":"email#email","name":"firstname", "summary":"testing","body":"testing","data":{"urlpage":"https://blabla.com/the/right/page/","name":"firstname","email":"email#email","commentaire":"testing"},"ip":"1.1.1.1","created_at":"2022-03-21T14:55:57.736Z","id":"aaaaaaaaa","form_id":"bbbbbbbb","site_url":"https://blabla.com","form_name":"approved-comments"}]
Here is my CommentForm code.
import React, { useReducer } from 'react';
import { makeStyles } from '#material-ui/core/styles';
import TextField from '#material-ui/core/TextField';
import { NetlifyForm, Honeypot } from 'react-netlify-forms'
import { useState } from "react"
import { useNetlifyForm, NetlifyFormProvider, NetlifyFormComponent} from "react-netlify-forms"
import { useFormik } from 'formik'
import { useLocation } from 'react-router-dom'
import "./styles.module.css";
const useStyles = makeStyles(theme => ({
input: {
minHeight: 100,
},
}));
const Commentbox = () => {
const classes = useStyles();
const netlify = useNetlifyForm({
name: 'approved-comments',
action: '/',
honeypotName: 'bot-field',
onSuccess: (response, context) => {
console.log('Successfully sent form data to Netlify Server')
}
})
const [touched, setTouched] = useState(false);
const location = useLocation();
const handleTouch = () => {
setTouched(true);
};
const {
handleSubmit,
handleChange,
handleBlur,
errors,
values
} = useFormik({
initialValues: { name: '', email: '', commentaire: '', urlpage: '' },
onSubmit: (values, {setStatus, resetForm}) => {
values.urlpage = "https://blabla.com" + location.pathname
netlify.handleSubmit(null, values);
resetForm();
setStatus({success: true});
},
validate: (values) => {
const errors = {}
if (
!/^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)
) {
errors.email = 'Adresse email invalide'
}
return errors
}
})
return (
<NetlifyFormProvider {...netlify}>
<input type="hidden" name="form-name" value="approved-comments" />
<h3>Leave a comment 😃</h3>
<NetlifyFormComponent onSubmit={handleSubmit}>
<Honeypot />
{netlify.success && (
<p sx={{ variant: 'alerts.success', p: 3 }}>
Thx for your comment 😃
</p>
)}
{netlify.error && (
<p sx={{ variant: 'alerts.muted', p: 3 }}>
Sorry 😢.
</p>
)}
<input
type="hidden"
name="urlpage"
id="urlpage"
/>
<TextField
required
id="name"
name='name'
label="Nom"
variant="outlined"
fullWidth
margin="normal"
onChange={handleChange}
onBlur={handleBlur}
error={errors.name}
value={values.name}
style = {{width: "70%"}}
/>
<TextField
required
id="email"
name='email'
label="Email"
variant="outlined"
fullWidth
margin="normal"
onChange={handleChange}
onBlur={handleBlur}
onFocus={handleTouch}
error={errors.email}
helperText={touched && !/^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email) ? 'Adresse email non valide' : ' '}
value={values.email}
style = {{width: "70%"}}
/>
<TextField
id="commentaire"
name='commentaire'
label="Commentaire"
variant="outlined"
fullWidth
margin="normal"
multiline
onChange={handleChange}
onBlur={handleBlur}
error={errors.commentaire}
value={values.commentaire}
inputProps={{
className: classes.input
}}
style = {{width: "70%"}}
/>
{/* <input type='hidden' name='name' value='values.name' />
<input type='hidden' name='email' value='values.email' />
<input type='hidden' name='commentaire' value='values.commentaire' /> */}
<button class="button button--lg button--primary" type="submit">
Publiez votre commentaire
</button>
</NetlifyFormComponent>
</NetlifyFormProvider>
)
}
export default Commentbox;
EDIT
So now my code compiles
import React, { useReducer } from 'react';
import "./styles.module.css";
import commentList from '../../../static/comments/approved-comments_submissions.json'
const Comments = commentList.map((item) => {
<ul>
<li>
<p>{item.data.name} a commenté le {item.created_on}</p>
<p>{item.data.commentaire}</p>
</li>
</ul>
} )
class CommentsList extends React.Component {
render() {
return (
<div>
{Comments}
</div>
);
}
}
export default CommentsList;
however comments are still not rendering below my comment form :/
I got same component with Antd form for add/edit article. With pathes in router
<Route path="/add" component={ !currentUser ? Login : ArticleEditor } />
<Route path="/article/:id/edit" component={ !currentUser ? Login : ArticleEditor } />
When I click "edit" button I add initialValues to form, than if I click "Create new article" url changes to "/add", but form didn't update values. Values remains from edited article. How to update form values? Tried to set initialValues depends at path, or "id" but its not worked. How to update antd form values in that case?
const initialValues = this.props.location.pathname === '/add' ? {} : {
title: this.props?.title,
body: this.props?.body,
description: this.props?.description
};
Here you can see the component code - codesandbox link
The main issue with the code is form fields are not reset when url is changed, you can detect path change in shouldComponentUpdate and set isLoading to true and rest should work.
Updating initialValues will not work because, antd does shallow compare and once initialValues are set, you will not be able to change them.
There was an issue in the logic of componentDidUpdate which I corrected as well.
import React from "react";
import ErrorsList from "../ErrorsList/ErrorsList";
import userService from "../../services/userService";
import { connect } from "react-redux";
import { push } from "react-router-redux";
import { Form, Input, Button } from "antd";
import { store } from "../../store";
import actionCreators from "../../actionCreators";
const formItemLayout = {
labelCol: { span: 24 },
wrapperCol: { span: 24 }
};
const formSingleItemLayout = {
wrapperCol: { span: 24, offset: 0 }
};
const mapStateToProps = (state) => ({
...state.editor
});
const mapDispatchToProps = (dispatch) => ({
onLoad: (payload) => dispatch(actionCreators.doEditorLoaded(payload)),
onUnload: () => dispatch(actionCreators.doEditorUnloaded()),
onUpdateField: (key, value) =>
dispatch(actionCreators.doUpdateFieldEditor(key, value)),
onSubmit: (payload, slug) => {
dispatch(actionCreators.doArticleSubmitted(payload));
store.dispatch(push(`/`)); //article/${slug}
},
onRedirect: () => dispatch(actionCreators.doRedirect())
});
class ArticleEditor extends React.Component {
constructor(props) {
super(props);
this.id = this.props.match.params.id;
const updateFieldEvent = (key) => (e) =>
this.props.onUpdateField(key, e.target.value);
this.changeTitle = updateFieldEvent("title");
this.changeDescription = updateFieldEvent("description");
this.changeBody = updateFieldEvent("body");
this.changeTagInput = updateFieldEvent("tagInput");
this.isLoading = true;
this.submitForm = () => {
const article = {
title: this.props.title,
description: this.props.description,
body: this.props.body,
tagList: this.props.tagInput.split(",")
};
const slug = { slug: this.props.articleSlug };
const promise = this.props.articleSlug
? userService.articles.update(Object.assign(article, slug))
: userService.articles.create(article);
this.props.onSubmit(promise, this.props.articleSlug);
};
}
componentDidUpdate(prevProps, prevState) {
if (this.props.match.params.id !== prevProps.match.params.id) {
if (prevProps.match.params.id) {
this.props.onUnload();
}
this.id = this.props.match.params.id;
if (this.id) {
return this.props.onLoad(userService.articles.get(this.id));
}
this.props.onLoad(null);
}
this.isLoading = false;
}
componentDidMount() {
if (this.id) {
this.isLoading = true;
return this.props.onLoad(userService.articles.get(this.id));
}
this.isLoading = false;
this.props.onLoad(null);
}
componentWillUnmount() {
this.props.onUnload();
}
shouldComponentUpdate(newProps, newState) {
if (this.props.match.params.id !== newProps.match.params.id) {
this.isLoading = true;
}
return true;
}
render() {
const { errors } = this.props;
const initialValues = {
title: this.props?.title,
body: this.props?.body,
description: this.props?.description,
tags: this.props?.tagList
};
return this.isLoading ? (
"loading..."
) : (
<div className="editor-page">
<div className="container page">
<div className="">
<div className="">
<ErrorsList errors={errors}></ErrorsList>
<Form
{...formItemLayout}
initialValues={initialValues}
onFinish={this.submitForm}
>
<Form.Item
label="Title"
name="title"
placeholder="Article Title"
rules={[
{
required: true,
message: "Please input article title"
}
]}
>
<Input onChange={this.changeTitle} />
</Form.Item>
<Form.Item
label="Description"
name="description"
placeholder="Short description"
rules={[
{
required: true,
message: "Please input article description"
}
]}
>
<Input onChange={this.changeDescription} />
</Form.Item>
<Form.Item
name="body"
label="Article Text"
placeholder="article text"
>
<Input.TextArea onChange={this.changeBody} />
</Form.Item>
<Form.Item name="tags" label="Tags" placeholder="Enter tags">
<Input onChange={this.changeTagInput} />
</Form.Item>
<Form.Item {...formSingleItemLayout}>
<Button
className="editor-form__btn"
type="primary"
htmlType="submit"
disabled={this.props.inProgress}
>
Submit Article
</Button>
</Form.Item>
</Form>
</div>
</div>
</div>
</div>
);
}
}
export default connect(mapStateToProps, mapDispatchToProps)(ArticleEditor);
take a look at this forked codesandbox.
You have to clean the fields before you re-use the 'ArticleEditor' component. Here you are using the same component for two different route, hence it's not changing.
You have to check if you are editing or adding a new entry to the Editor. Your editor component may look like this then,
const ArticleEditor = props => {
const [form] = Form.useForm();
useEffect(() => {
if (props.match.params.id) form.setFieldsValue({value : 'Some values'})
else form.resetFields()
}, [props?.match?.params]);
return (
<Form form={form} onFinish={yourFinishMethod}>
//...your form fields
</Form>
)
}
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.