从不传递 Props 的 Child 组件表单获取输入?
Get Inputs From Child Component Form That Doesn't Pass Props?
在下面的 Parent 组件中,我有一个包含两个选项的下拉列表。如果您 select "TOP LEVEL",那么将显示一个名为 Form1 的表单。如果我选择 "MAKE ITEM",那么将显示一个名为 Form2 的表单。如果什么都不 selected 则两种形式都被隐藏。我的 Parent 组件中有一个按钮,我想提交显示的当前表单中的任何输入。因此,如果 "TOP LEVEL" 被 selected,并且单击了按钮,我想记录来自 Form1 的输入。这可能吗?还是我需要将所有内容都放在一个组件中?如果可能的话,我需要使用 Formik 吗?如果我处理这个错误,请提出更好的方法。
Parent 组件
import * as React from "react";
import { Dropdown, DropdownMenuItemType, IDropdownOption } from 'office-ui-fabric-react/lib/Dropdown';
import { PrimaryButton } from 'office-ui-fabric-react/lib/';
import Form1 from './Form1';
import Form2 from './Form2';
export interface ParentProps {
};
export interface ParentState {
selectedItem?: { key: string | number | undefined };
operationType?;
formName?
};
export default class ParentComponent extends React.Component<ParentProps, ParentState> {
constructor(props, context) {
super(props, context);
this.state = {
operationType: '',
formName: '',
};
}
addToExcel = async () => {
try {
await Excel.run(async context => {
const range = context.workbook.getSelectedRange();
range.load("address");
await context.sync();
console.log(`The range address was ${range.address}.`);
});
} catch (error) {
console.error(error);
}
this.setState({
operationType: '',
})
};
render(){
const { selectedItem } = this.state;
const options: IDropdownOption[] = [
{ key: 'blank', text: '' },
{ key: 'topLevelMake', text: 'Parents', itemType: DropdownMenuItemType.Header },
{ key: 'topLevel', text: 'TOP LEVEL' },
{ key: 'make', text: 'MAKE ITEM' },
];
return(
<div>
<Dropdown
label="Operation"
selectedKey={selectedItem ? selectedItem.key : undefined}
onChange={this._onChange}
placeholder={"Select an option"}
options={options}
styles={{ dropdown: { width: 300 } }}
/>
{this.state.formName}
<p></p>
<PrimaryButton
text="Enter"
onClick={this.addToExcel}
/>
</div>
);
}
private _onChange = (event: React.FormEvent<HTMLDivElement>, item: IDropdownOption): void => {
this.setState({ selectedItem: item });
this.setState({operationType: item.text})
console.log(event);
let Form = <div />;
switch (item.text) {
case "TOP LEVEL":
Form = <Form1 /> ;
this.setState({formName: Form});
break;
case "MAKE ITEM":
Form = <Form2 /> ;
this.setState({formName: Form});
break;
default:
Form = <div></div>
break;
}
};
}
Form1(Form2类似所以我不包括)
import * as React from "react";
import { TextField } from 'office-ui-fabric-react/lib/';
export interface Form1Props {
};
export interface Form1State {
dataGoToExcel?;
dataGoToExcel2?;
};
export default class Form1 extends React.Component<Form1Props, Form1State> {
constructor(props, context) {
super(props, context);
this.state = {
dataGoToExcel: '',
dataGoToExcel2: '',
};
}
handleChange = (event) => {
this.setState({
dataGoToExcel: event.target.value,
})
};
handleChange2 = (event) => {
this.setState({
dataGoToExcel2: event.target.value,
})
};
render(){
return(
<div>
<TextField
label="TextField"
type="text"
value={this.state.dataGoToExcel}
onChange={this.handleChange}
/>
<TextField
label="Another TextField"
type="text"
value={this.state.dataGoToExcel2}
onChange={this.handleChange2}
/>
</div>
);
}
};
编辑:
Parent
import * as React from "react";
import { Dropdown, DropdownMenuItemType, IDropdownOption } from 'office-ui-fabric-react/lib/Dropdown';
import { PrimaryButton } from 'office-ui-fabric-react/lib/';
import Form1 from './Form1';
//import Form2 from './Form2';
export interface ParentProps {
};
export interface ParentState {
selectedItem?: { key: string | number | undefined };
operationType?;
formName?;
formData;
updateFormData?;
};
export default class ParentComponent extends React.Component<ParentProps, ParentState> {
constructor(props, context) {
super(props, context);
this.state = {
operationType: '',
formName: '',
formData: ''
};
}
updateFormData = (data) => this.setState({ formData: data })
addToExcel = async () => {
try {
await Excel.run(async context => {
const range = context.workbook.getSelectedRange();
range.load("address");
await context.sync();
console.log((`The range address was ${this.state.formData}.`))
});
} catch (error) {
console.error(error);
}
this.setState({
operationType: '',
formData: '',
formName: '',
})
};
render() {
const { selectedItem } = this.state;
const options: IDropdownOption[] = [
{ key: 'blank', text: '' },
{ key: 'topLevelMake', text: 'Parents', itemType: DropdownMenuItemType.Header },
{ key: 'topLevel', text: 'TOP LEVEL' },
{ key: 'make', text: 'MAKE ITEM' },
];
return (
<div>
<Dropdown
label="Operation"
selectedKey={selectedItem ? selectedItem.key : undefined}
onChange={this._onChange}
placeholder={"Select an option"}
options={options}
styles={{ dropdown: { width: 300 } }}
/>
{this.state.formName}
<p></p>
<PrimaryButton
text="Enter"
onClick={this.addToExcel}
/>
</div>
);
}
private _onChange = (event: React.FormEvent<HTMLDivElement>, item: IDropdownOption): void => {
this.setState({ selectedItem: item });
this.setState({ operationType: item.text })
console.log(event);
let Form = <div />;
switch (item.text) {
case "TOP LEVEL":
Form = <Form1 formData={this.state.formData} onDataChange={this.updateFormData} />;
this.setState({ formName: Form });
break;
//case "MAKE ITEM":
// Form = <Form2 formData={this.state.formName} onDataChange={this.updateFormData} />;
// this.setState({ formName: Form });
// break;
default:
Form = <div></div>
break;
}
};
}
Form1(注释掉 Form2)
import * as React from "react";
import { TextField } from 'office-ui-fabric-react/lib/';
export interface Form1Props {
formData: any /* Type of form data */
onDataChange: (data: any) => void
};
export default class Form1 extends React.Component<Form1Props> {
handleChange = (event: any) => {
const data = this.props.formData & event.target.value; /* merge props.formdata and event.target.value*/
this.props.onDataChange(data)
};
handleChange2 = (event: any) => {
const data = this.props.formData & event.target.value;/* merge props.formdata and event.target.value*/
this.props.onDataChange(data)
};
render(){
return (
<div>
<TextField
label="TextField"
type="text"
value={this.props.formData.dataGoToExcel}
onChange={this.handleChange}
/>
<TextField
label="Another TextField"
type="text"
value={this.props.formData.dataGoToExcel2}
onChange={this.handleChange2}
/>
</div>
);
}
};
一种方法是
- 具有将表单数据更新为 Parent 状态的功能
- 将此函数作为 props 传递给 Form 1 和 2。
- 对于表单中的任何更新,必须调用此函数来更新parent状态
- 这些更新后的值也必须作为 props 流向 children。
最后,点击Parent中的按钮,就可以提交状态中的内容了。
您必须将局部状态从 Form1 和 Form2 上移到 parent 并将必要的表单值作为 props 发送给 child 组件并且 child 没有局部状态需要组件
编辑:
Parent 组件
export default class ParentComponent extends React.Component<ParentProps, ParentState> {
constructor(props, context) {
super(props, context);
this.state = {
operationType: '',
formName: '',
formData: {/*data as object*/ }
};
}
updateFormData = (data) => this.setState({ formData: data })
addToExcel = async () => {
try {
await Excel.run(async context => {
const range = context.workbook.getSelectedRange();
range.load("address");
await context.sync();
console.log(`The range address was ${range.address}.`);
});
} catch (error) {
console.error(error);
}
this.setState({
operationType: '',
})
};
render() {
const { selectedItem } = this.state;
const options: IDropdownOption[] = [
{ key: 'blank', text: '' },
{ key: 'topLevelMake', text: 'Parents', itemType: DropdownMenuItemType.Header },
{ key: 'topLevel', text: 'TOP LEVEL' },
{ key: 'make', text: 'MAKE ITEM' },
];
return (
<div>
<Dropdown
label="Operation"
selectedKey={selectedItem ? selectedItem.key : undefined}
onChange={this._onChange}
placeholder={"Select an option"}
options={options}
styles={{ dropdown: { width: 300 } }}
/>
{this.state.formName}
<p></p>
<PrimaryButton
text="Enter"
onClick={this.addToExcel}
/>
</div>
);
}
private _onChange = (event: React.FormEvent<HTMLDivElement>, item: IDropdownOption): void => {
this.setState({ selectedItem: item });
this.setState({ operationType: item.text })
console.log(event);
let Form = <div />;
switch (item.text) {
case "TOP LEVEL":
Form = <Form1 formData={this.state.formData} onDataChange={this.updateFormData} />;
this.setState({ formName: Form });
break;
case "MAKE ITEM":
Form = <Form2 formData={this.state.formData} onDataChange={this.updateFormData} />;
this.setState({ formName: Form });
break;
default:
Form = <div></div>
break;
}
};
}
表单 1 组件
import * as React from "react";
import { TextField } from 'office-ui-fabric-react/lib/';
export interface Form1Props {
formData: any /* Type of form data */
onDataChange: (data: any) => void
};
export default class Form1 extends React.Component<Form1Props> {
handleChange = (event) => {
const data = /* merge props.formdata and event.target.value*/
this.props.onDataChange(data)
};
handleChange2 = (event) => {
const data = /* merge props.formdata and event.target.value*/
this.props.onDataChange(data)
};
render(){
return (
<div>
<TextField
label="TextField"
type="text"
value={this.props.formData.dataGoToExcel}
onChange={this.handleChange}
/>
<TextField
label="Another TextField"
type="text"
value={this.props.formData.dataGoToExcel2}
onChange={this.handleChange2}
/>
</div>
);
}
};
在下面的 Parent 组件中,我有一个包含两个选项的下拉列表。如果您 select "TOP LEVEL",那么将显示一个名为 Form1 的表单。如果我选择 "MAKE ITEM",那么将显示一个名为 Form2 的表单。如果什么都不 selected 则两种形式都被隐藏。我的 Parent 组件中有一个按钮,我想提交显示的当前表单中的任何输入。因此,如果 "TOP LEVEL" 被 selected,并且单击了按钮,我想记录来自 Form1 的输入。这可能吗?还是我需要将所有内容都放在一个组件中?如果可能的话,我需要使用 Formik 吗?如果我处理这个错误,请提出更好的方法。
Parent 组件
import * as React from "react";
import { Dropdown, DropdownMenuItemType, IDropdownOption } from 'office-ui-fabric-react/lib/Dropdown';
import { PrimaryButton } from 'office-ui-fabric-react/lib/';
import Form1 from './Form1';
import Form2 from './Form2';
export interface ParentProps {
};
export interface ParentState {
selectedItem?: { key: string | number | undefined };
operationType?;
formName?
};
export default class ParentComponent extends React.Component<ParentProps, ParentState> {
constructor(props, context) {
super(props, context);
this.state = {
operationType: '',
formName: '',
};
}
addToExcel = async () => {
try {
await Excel.run(async context => {
const range = context.workbook.getSelectedRange();
range.load("address");
await context.sync();
console.log(`The range address was ${range.address}.`);
});
} catch (error) {
console.error(error);
}
this.setState({
operationType: '',
})
};
render(){
const { selectedItem } = this.state;
const options: IDropdownOption[] = [
{ key: 'blank', text: '' },
{ key: 'topLevelMake', text: 'Parents', itemType: DropdownMenuItemType.Header },
{ key: 'topLevel', text: 'TOP LEVEL' },
{ key: 'make', text: 'MAKE ITEM' },
];
return(
<div>
<Dropdown
label="Operation"
selectedKey={selectedItem ? selectedItem.key : undefined}
onChange={this._onChange}
placeholder={"Select an option"}
options={options}
styles={{ dropdown: { width: 300 } }}
/>
{this.state.formName}
<p></p>
<PrimaryButton
text="Enter"
onClick={this.addToExcel}
/>
</div>
);
}
private _onChange = (event: React.FormEvent<HTMLDivElement>, item: IDropdownOption): void => {
this.setState({ selectedItem: item });
this.setState({operationType: item.text})
console.log(event);
let Form = <div />;
switch (item.text) {
case "TOP LEVEL":
Form = <Form1 /> ;
this.setState({formName: Form});
break;
case "MAKE ITEM":
Form = <Form2 /> ;
this.setState({formName: Form});
break;
default:
Form = <div></div>
break;
}
};
}
Form1(Form2类似所以我不包括)
import * as React from "react";
import { TextField } from 'office-ui-fabric-react/lib/';
export interface Form1Props {
};
export interface Form1State {
dataGoToExcel?;
dataGoToExcel2?;
};
export default class Form1 extends React.Component<Form1Props, Form1State> {
constructor(props, context) {
super(props, context);
this.state = {
dataGoToExcel: '',
dataGoToExcel2: '',
};
}
handleChange = (event) => {
this.setState({
dataGoToExcel: event.target.value,
})
};
handleChange2 = (event) => {
this.setState({
dataGoToExcel2: event.target.value,
})
};
render(){
return(
<div>
<TextField
label="TextField"
type="text"
value={this.state.dataGoToExcel}
onChange={this.handleChange}
/>
<TextField
label="Another TextField"
type="text"
value={this.state.dataGoToExcel2}
onChange={this.handleChange2}
/>
</div>
);
}
};
编辑:
Parent
import * as React from "react";
import { Dropdown, DropdownMenuItemType, IDropdownOption } from 'office-ui-fabric-react/lib/Dropdown';
import { PrimaryButton } from 'office-ui-fabric-react/lib/';
import Form1 from './Form1';
//import Form2 from './Form2';
export interface ParentProps {
};
export interface ParentState {
selectedItem?: { key: string | number | undefined };
operationType?;
formName?;
formData;
updateFormData?;
};
export default class ParentComponent extends React.Component<ParentProps, ParentState> {
constructor(props, context) {
super(props, context);
this.state = {
operationType: '',
formName: '',
formData: ''
};
}
updateFormData = (data) => this.setState({ formData: data })
addToExcel = async () => {
try {
await Excel.run(async context => {
const range = context.workbook.getSelectedRange();
range.load("address");
await context.sync();
console.log((`The range address was ${this.state.formData}.`))
});
} catch (error) {
console.error(error);
}
this.setState({
operationType: '',
formData: '',
formName: '',
})
};
render() {
const { selectedItem } = this.state;
const options: IDropdownOption[] = [
{ key: 'blank', text: '' },
{ key: 'topLevelMake', text: 'Parents', itemType: DropdownMenuItemType.Header },
{ key: 'topLevel', text: 'TOP LEVEL' },
{ key: 'make', text: 'MAKE ITEM' },
];
return (
<div>
<Dropdown
label="Operation"
selectedKey={selectedItem ? selectedItem.key : undefined}
onChange={this._onChange}
placeholder={"Select an option"}
options={options}
styles={{ dropdown: { width: 300 } }}
/>
{this.state.formName}
<p></p>
<PrimaryButton
text="Enter"
onClick={this.addToExcel}
/>
</div>
);
}
private _onChange = (event: React.FormEvent<HTMLDivElement>, item: IDropdownOption): void => {
this.setState({ selectedItem: item });
this.setState({ operationType: item.text })
console.log(event);
let Form = <div />;
switch (item.text) {
case "TOP LEVEL":
Form = <Form1 formData={this.state.formData} onDataChange={this.updateFormData} />;
this.setState({ formName: Form });
break;
//case "MAKE ITEM":
// Form = <Form2 formData={this.state.formName} onDataChange={this.updateFormData} />;
// this.setState({ formName: Form });
// break;
default:
Form = <div></div>
break;
}
};
}
Form1(注释掉 Form2)
import * as React from "react";
import { TextField } from 'office-ui-fabric-react/lib/';
export interface Form1Props {
formData: any /* Type of form data */
onDataChange: (data: any) => void
};
export default class Form1 extends React.Component<Form1Props> {
handleChange = (event: any) => {
const data = this.props.formData & event.target.value; /* merge props.formdata and event.target.value*/
this.props.onDataChange(data)
};
handleChange2 = (event: any) => {
const data = this.props.formData & event.target.value;/* merge props.formdata and event.target.value*/
this.props.onDataChange(data)
};
render(){
return (
<div>
<TextField
label="TextField"
type="text"
value={this.props.formData.dataGoToExcel}
onChange={this.handleChange}
/>
<TextField
label="Another TextField"
type="text"
value={this.props.formData.dataGoToExcel2}
onChange={this.handleChange2}
/>
</div>
);
}
};
一种方法是
- 具有将表单数据更新为 Parent 状态的功能
- 将此函数作为 props 传递给 Form 1 和 2。
- 对于表单中的任何更新,必须调用此函数来更新parent状态
- 这些更新后的值也必须作为 props 流向 children。
最后,点击Parent中的按钮,就可以提交状态中的内容了。
您必须将局部状态从 Form1 和 Form2 上移到 parent 并将必要的表单值作为 props 发送给 child 组件并且 child 没有局部状态需要组件
编辑:
Parent 组件
export default class ParentComponent extends React.Component<ParentProps, ParentState> {
constructor(props, context) {
super(props, context);
this.state = {
operationType: '',
formName: '',
formData: {/*data as object*/ }
};
}
updateFormData = (data) => this.setState({ formData: data })
addToExcel = async () => {
try {
await Excel.run(async context => {
const range = context.workbook.getSelectedRange();
range.load("address");
await context.sync();
console.log(`The range address was ${range.address}.`);
});
} catch (error) {
console.error(error);
}
this.setState({
operationType: '',
})
};
render() {
const { selectedItem } = this.state;
const options: IDropdownOption[] = [
{ key: 'blank', text: '' },
{ key: 'topLevelMake', text: 'Parents', itemType: DropdownMenuItemType.Header },
{ key: 'topLevel', text: 'TOP LEVEL' },
{ key: 'make', text: 'MAKE ITEM' },
];
return (
<div>
<Dropdown
label="Operation"
selectedKey={selectedItem ? selectedItem.key : undefined}
onChange={this._onChange}
placeholder={"Select an option"}
options={options}
styles={{ dropdown: { width: 300 } }}
/>
{this.state.formName}
<p></p>
<PrimaryButton
text="Enter"
onClick={this.addToExcel}
/>
</div>
);
}
private _onChange = (event: React.FormEvent<HTMLDivElement>, item: IDropdownOption): void => {
this.setState({ selectedItem: item });
this.setState({ operationType: item.text })
console.log(event);
let Form = <div />;
switch (item.text) {
case "TOP LEVEL":
Form = <Form1 formData={this.state.formData} onDataChange={this.updateFormData} />;
this.setState({ formName: Form });
break;
case "MAKE ITEM":
Form = <Form2 formData={this.state.formData} onDataChange={this.updateFormData} />;
this.setState({ formName: Form });
break;
default:
Form = <div></div>
break;
}
};
}
表单 1 组件
import * as React from "react";
import { TextField } from 'office-ui-fabric-react/lib/';
export interface Form1Props {
formData: any /* Type of form data */
onDataChange: (data: any) => void
};
export default class Form1 extends React.Component<Form1Props> {
handleChange = (event) => {
const data = /* merge props.formdata and event.target.value*/
this.props.onDataChange(data)
};
handleChange2 = (event) => {
const data = /* merge props.formdata and event.target.value*/
this.props.onDataChange(data)
};
render(){
return (
<div>
<TextField
label="TextField"
type="text"
value={this.props.formData.dataGoToExcel}
onChange={this.handleChange}
/>
<TextField
label="Another TextField"
type="text"
value={this.props.formData.dataGoToExcel2}
onChange={this.handleChange2}
/>
</div>
);
}
};