I am recently developing an email list using React Table. There is a BCC field that allows users to insert an email address. I have implemented App.tsx as the Root component and EmailForm.tsx as the child one.
After every action from Child (Insert characters in BCC, select the checkboxes), an update email list is sent from the Child to Parent component where all main activities will be handled.
I am facing a problem that every time I try to insert a new character in BCC input, "onChange" event just takes one character and not the whole input text area.
I followed this thread, but it did not help.
My repo: https://codesandbox.io/s/thirsty-ellis-2981iv
My Parent component: App.tsx
import React, { Component } from "react";
import { Formik } from "formik";
import './App.css';
import EmailForm from "./EmailForm";
interface IEmail {
"title": number;
"checkList": ICheckList[];
"bcc": IBcc;
}
interface ICheckList {
"isEnable": boolean;
"email": string
}
interface IBcc {
"isEnable": boolean;
"email": string
}
const defaults = [
{
title: "title-1",
checkList: [{
isEnable: true,
email: "title-1.1@mail.com"
},
{
isEnable: true,
email: "title-1.2@mail.com"
}],
bcc: {
isEnable: true,
email: ""
}
},
{
title: "title-2",
checkList: [{
isEnable: true,
email: "title-2@mail.com"
}],
bcc: {
isEnable: true,
email: ""
}
},
{
title: "title-3",
checkList: [{
isEnable: true,
email: "title-3@mail.com"
}],
bcc: {
isEnable: true,
email: ""
}
}
];
class App extends Component {
state = {
data: defaults,
}
getInitialValues = () => {
const initialValues = {
...defaults
};
return initialValues;
}
handleBccInput = (index: number, event: string) => {
console.log('handleBccInput index: ' + index + ' bccInput : ' + event)
let data = [...this.state.data];
//console.log('data: ' + JSON.stringify(data));
data[index].bcc.email = event;
console.log('data[index].bcc.email: ' + data[index].bcc.email);
this.setState({ data });
}
onSubmit = () => {
console.log('onSubmit clicked')
}
handleCheckboxSelected = (emailIdx: number, addressIdx: number) => {
let data = [...this.state.data];
data[emailIdx].checkList[addressIdx].isEnable = !data[emailIdx].checkList[addressIdx].isEnable
this.setState({ data });
}
render() {
const initialValues = this.getInitialValues();
const renderForm = (props: any) => (
<EmailForm
{...props}
data={this.state.data}
handleBccInput={this.handleBccInput}
handleCheckboxSelected={this.handleCheckboxSelected}
/>
);
return (
<React.Fragment >
<Formik
// tslint:disable-next-line jsx-no-lambda
render={props => renderForm(props)}
initialValues={initialValues}
onSubmit={this.onSubmit}
validateOnBlur={true}
validateOnChange={true} />
</React.Fragment>
);
}
}
export default App;
My Child component: EmailForm.tsx:
import React, { Component } from "react";
import { Form, FormikProps } from "formik";
import { WithTranslation, withTranslation } from "react-i18next";
import ReactTable, { Column } from "react-table";
import "react-table/react-table.css";
interface IEmail {
"title": number;
"checkList": ICheckList[];
"bcc": IBcc;
}
interface ICheckList {
"isEnable": boolean;
"email": string
}
interface IBcc {
"isEnable": boolean;
"email": string
}
interface IState {
data: IEmail[],
handleBccInput(index: any, event: string): any,
handleCheckboxSelected(emailIndex: number, addressIndex: number): any,
}
class EmailForm extends Component<IEmail & IState & WithTranslation> {
renderCheckbox = (title: string) => {
return (
<div>{title}</div>
);
}
overrideValue = (index: number, override: any) => {
//console.log('index: ' + index + ' override: ' + override)
this.props.handleBccInput(index, override)
}
onCheckBoxItemSelected = (emailIndex: number, addressIndex: number) => {
this.props.handleCheckboxSelected(emailIndex, addressIndex)
}
renderHeader = (title: string) => {
return (
<div
style={{
textAlign: "center",
}}
>{title}</div>
);
}
tableHeader = (): Array<Column<IEmail>> => {
// Extract transalation variable from props
return [
{
Header: this.renderHeader('Title'),
id: "title",
accessor: "title",
width: 200,
Cell: props => {
return (
<input value={props.value} readOnly></input>
)
},
},
{
Header: this.renderHeader("Check List"),
id: "checkList",
accessor: "checkList",
sortable: false,
width: 200,
resizable: true,
Cell: props => {
const cellValues = props.value
//console.log('cell.value : ' + JSON.stringify(cellValues))
return cellValues.map((item: ICheckList, index: number) => {
return (
<div>
<input type="checkbox" checked={item.isEnable} onChange={() => this.onCheckBoxItemSelected(props.index, index)} />
<a>{item.email}</a>
</div>
)
})
}
},
{
Header: this.renderHeader("BCC"),
id: "bcc",
accessor: "bcc",
Cell: props => {
return (
<input disabled={!props.value.isEnable} value={props.value.email} onChange={e => { this.overrideValue(props.index, e.target.value) }} type="text" ></input>
)
},
width: 200,
}
];
}
/*
Component render function
*/
render() {
const {
t,
data,
} = this.props
const emptyElement = () => null;
const tableHeader = this.tableHeader();
return (
<Form className="email-container-form">
<ReactTable
columns={tableHeader}
resizable={false}
data={data}
loading={false}
showPagination={false}
NoDataComponent={emptyElement}
defaultPageSize={Number.MAX_SAFE_INTEGER}
minRows={1}
/>
</Form>
)
}
}
export default withTranslation()(EmailForm);