React 父给子组件传值,未取到
2处有值,说明值已经传过来了,1处 为什么无值 ?
在父组件调取接口,返回的数据,用 setState 设置后,然后传给子组件,用于数据 回显.
在点击"编辑"进入当前页面后(当前页用于回显),"1"处被执行1次,无值, "2"处竟然被 执行了 17 次! 从第 12 次开始,才有值, 之前也是无值的.
在两个组件里使用了相同的方法,一个能取到值,一个取不到.代码在下面.
父组件这样传值:
<ConnectForm tableRelationsData={this.state.tableRelationsList} />
子组件代码片断:
constructor(props: ConnectFormProps) {
super(props);
this.tableRelationsData = [];
this.notTableRelationsData = [];
console.log(props.tableRelationsData) //1无值
props.tableRelationsData.forEach(item => {
... ...
render() {
const { tableRelationsData} = this.props;
console.log(tableRelationsData); //2有值
==================================================
可以简单看下,好用组件 和 不好用组件,差在哪里:
好用的组件:
import { Form, Input, Modal, Table, message } from "antd";
... ...
export interface FormValueType extends Partial<TableListItem> {
target?: string;
template?: string;
type?: string;
time?: string;
frequency?: string;
}
export interface TableFormProps extends FormComponentProps {
onCancel: (flag?: boolean, formVals?: FormValueType) => void;
onSubmit: (values: FormValueType) => void;
TableModalVisible: boolean;
values: Partial<TableListItem>;
onAddTableForm: any;
}
const columns = [
{
title: "序号",
dataIndex: "index",
render: text => <a>{text}</a>
},
{
title: "字段名",
dataIndex: "name"
},
{
title: "数据类型",
dataIndex: "type"
},
// {
// title: "长度",
// dataIndex: "length"
// },
{
title: "描述",
dataIndex: "fieldDesc"
}
// {
// title: "可为空",
// dataIndex: "isNull",
// render(isNull) {
// return isNull == 1 ? "YES" : "NO";
// }
// }
];
const data = [
{
key: "1",
index: 1,
fieldName: "Name",
dataType: "VARCHSR2",
length: 255,
isNull: 2
},
{
key: "2",
index: 2,
fieldName: "INFO1",
dataType: "VARCHSR2",
length: 255,
isNull: 1
},
{
key: "3",
index: 3,
fieldName: "Name",
dataType: "VARCHSR2",
length: 32,
isNull: 2
},
{
key: "4",
index: 4,
fieldName: "TYPE",
dataType: "VARCHSR2",
length: 255,
isNull: 1
}
];
export interface TableFormState {
formVals: FormValueType;
}
function hasErrors(fieldsError) {
return Object.keys(fieldsError).some(field => fieldsError[field]);
}
class TableForm extends Component<TableFormProps, TableFormState> {
tableFormData: {
key: string;
index: number;
fieldName: string;
dataType: string;
length: number;
isNull: number;
}[];
state = {
selectedRowKeys: [], // Check here to configure the default column
selectedRows: [],
formVals: {},
tableFormData: {},
metaDataTitle: {},
tableAliasName: {},
tableFormDataAll: {
selectedRows: [],
tableAliasName: ""
},
loading: true,
selectChangeSign: number
};
static defaultProps = {
handleUpdate: () => {},
handleTableModalVisible: () => {},
values: {}
};
formLayout = {
labelCol: { span: 7 },
wrapperCol: { span: 13 }
};
constructor(props: TableFormProps) {
super(props);
//修改部分1
//拆分数据
this.nodeData = [];
this.notNodeData = [];
props.nodeData.forEach(item => {
if (item.id.slice(-8) === props.model.id) { // 原判断: item.nodeId === props.model.id 新判断:item.id.slice(-8)
this.nodeData.push(item);
} else {
this.notNodeData.push(item);
}
});
console.log(props.nodeData);
let selectedRowKeys = this.nodeData.map(item => item.name);
this.aliasName =
this.nodeData[0] === undefined ? "" : this.nodeData[0].tableAliasName;
//修改部分1
this.state = {
formVals: {
name: props.values.name,
desc: props.values.desc,
key: props.values.key,
target: "0",
template: "0",
type: "1",
time: "",
frequency: "month"
},
selectedRowKeys: selectedRowKeys,
tableFormData: {},
metaDataTitle: {},
selectedRows: [],
tableAliasName: this.aliasName,
loading: true,
};
console.log("我是构造函数,我被触发了");
}
GenNonDuplicateID = (randomLength: any) => {
return Number(
Math.random()
.toString()
.substr(3, randomLength) + Date.now()
).toString(36);
};
okHandle = e => {
const { tableAliasName, selectedRows } = this.state;
if (!tableAliasName) {
return message.warning("请输入表的别名");
}
if (!selectedRows) {
return message.warning("请选择你想要的字段");
}
console.log(selectedRows)
//修改5,如果selectedRows无值,则赋原值
if(selectedRows.length == 0){
this.state.selectedRows = this.nodeData
}
//修改5
// console.log(this.state.selectedRows);
console.log(this.state.tableAliasName);
const newSelectedRowsAll: any[] = [];
this.state.selectedRows.forEach((item: any, index: any) => {
const newSelectedRows = {
id: item.id,
isAggregation: false,
name: item.name,
orderInfo: "NONE",
tableAliasName: this.state.tableAliasName,
type: item.type,
nodeId: this.props.model.id //
};
newSelectedRowsAll.push(newSelectedRows);
});
console.log(newSelectedRowsAll);
//修改4
this.props.onAddTableForm([...newSelectedRowsAll, ...this.notNodeData]);
//修改4
this.state.selectedRows = "";
this.state.selectedRowKeys = "";
this.props.CloseTableModalVisible();
let getTableAliasName = this.props.form.getFieldsValue();
this.props.form.validateFields((err, values) => {
if (!err) {
message.success(
`${getTableAliasName.tableAliasName} 这是用户输入的 别名`
);
}
});
};
onSelectChange = (selectedRowKeys, selectedRows) => {
const that = this;
console.log("selectedRowKeys changed: ", selectedRowKeys);
console.log("selectedRows changed: ", selectedRows);
setTimeout(() => {
that.setState({
selectedRowKeys,
selectedRows
});
}, 100);
};
handleCancel = e => {
console.log(e);
this.props.CloseTableModalVisible();
};
onChange = ({ target: { value } }) => {
this.setState({ textArea: [value] });
console.log(value);
this.setState({ tableAliasName: value });
};
render() {
const {
getFieldDecorator,
getFieldsError,
getFieldError,
isFieldTouched
} = this.props.form;
//修改部分3
const {
TableModalVisible,
onCancel: handleTableModalVisible,
model
} = this.props;
let tableFormData = this.props.tableFormData.map(item => {
let data = JSON.parse(JSON.stringify(item));
data.key = data.name;
console.log(data)
return data;
});
//修改部分3
console.log(tableFormData);
console.log(this.props.tableFormData);
const { loading, selectedRowKeys } = this.state;
const rowSelection = {
selectedRowKeys,
onChange: this.onSelectChange
};
console.log(this.aliasName);
return (
<Modal
width={740}
destroyOnClose
title="设置表组件"
visible={TableModalVisible}
onOk={this.okHandle}
// onCancel={() => handleTableModalVisible(false, values)}
onCancel={this.handleCancel}
// afterClose={() => handleTableModalVisible()}
maskClosable={false}
cancelText={"重置"}
okText={"保存"}
>
<Form layout="vertical">
<Form.Item label="标题">
<Input disabled value={model.label} />
</Form.Item>
<Form.Item label="表名schema">
<Input disabled value={model.desSchema} />
</Form.Item>
<Form.Item label="请输入表的别名">
{getFieldDecorator("tableAliasName", {
initialValue: this.aliasName,
rules: [
{
required: true,
message: "别名不能为空"
}
]
})(
<Input
// className={styles.datainput}
placeholder="请输入表的别名"
onChange={this.onChange}
/>
)}
</Form.Item>
<Form.Item label="请选择你想要的字段">
<div id="components-table-demo-row-selection">
<Table
rowSelection={rowSelection}
columns={columns}
dataSource={tableFormData}
size="small"
/>
</div>
</Form.Item>
</Form>
</Modal>
);
}
}
export default Form.create<TableFormProps>()(TableForm);
不好用的组件:
import {... ...} from "antd";
import React, { Component } from "react";
import { FormComponentProps } from "antd/es/form";
import { TableListItem } from "../data.d";
const { Option } = Select;
const EditableContext = React.createContext();
const EditableRow = ({ form, index, ...props }) => (
<EditableContext.Provider value={form}>
<tr {...props} />
</EditableContext.Provider>
);
const EditableFormRow = Form.create()(EditableRow);
export interface FormValueType extends Partial<TableListItem> {
target?: string;
template?: string;
type?: string;
time?: string;
frequency?: string;
}
export interface ConnectFormProps extends FormComponentProps {
onCancel: (flag?: boolean, formVals?: FormValueType) => void;
onSubmit: (values: FormValueType) => void;
ConnectModalVisible: boolean;
values: Partial<TableListItem>;
}
export interface ConnectFormState {
formVals: FormValueType;
}
class EditableCell extends React.Component {
constructor(props: ConnectFormProps) {
super(props);
}
state = {
editing: false,
selectList: []
};
toggleEdit = () => {
const editing = !this.state.editing;
this.setState({ editing }, () => {
if (editing) {
this.input.focus();
}
});
};
save = e => {
const { record, handleSave } = this.props;
this.form.validateFields((error, values) => {
if (error && error[e.currentTarget.id]) {
return;
}
//this.toggleEdit();
handleSave({ ...record, ...values });
});
};
handleSelectChange = value => {
console.log(value);
this.form.setFieldsValue({
selectValue: `${value}`
});
};
renderCell = form => {
this.form = form;
const {
children,
dataIndex,
record,
title,
connectFormData,
tableFormData
} = this.props;
console.log(connectFormData);
console.log(tableFormData);
const { editing } = this.state;
const { getFieldDecorator } = this.form;
if (dataIndex == "MainTablefield") {
let i = 0;
return (
<Form.Item style={{ margin: 0 }}>
{form.getFieldDecorator(dataIndex, {
initialValue: "请选择主表字段" //record[dataIndex]
})(
<Select
className="table-user-name-input"
showSearch
placeholder="请选择主表字段"
optionFilterProp="children"
onChange={this.onChange}
onBlur={this.save}
labelInValue
filterOption={(input, option) =>
option.props.children
.toLowerCase()
.indexOf(input.toLowerCase()) >= 0
}
>
{tableFormData.map((item, index) => {
if (item.id.slice(-8) == connectFormData.nodeSourceId) {
return (
<Option key={index} value={index}>
{item.name}
</Option>
);
}
})}
</Select>
)}
</Form.Item>
);
} else if (dataIndex == "operator") {
return (
<Form.Item style={{ margin: 0 }}>
{form.getFieldDecorator(dataIndex, {
initialValue: "请选择运算符" //record[dataIndex]
})(
<Select
className="table-user-name-input"
showSearch
placeholder="请选择运算符"
optionFilterProp="children"
onChange={this.onChange}
onBlur={this.save}
labelInValue
filterOption={(input, option) =>
option.props.children
.toLowerCase()
.indexOf(input.toLowerCase()) >= 0
}
>
<Option key="0" value=">">
大于
</Option>
<Option key="1" value="=">
等于
</Option>
<Option key="2" value="<">
小于
</Option>
</Select>
)}
</Form.Item>
);
} else if (dataIndex == "auxiliaryTablefield") {
return (
<Form.Item style={{ margin: 0 }}>
{form.getFieldDecorator(dataIndex, {
initialValue: "请选择连接表字段" //record[dataIndex]
})(
<Select
className="table-user-name-input"
showSearch
placeholder="请选择连接表字段"
optionFilterProp="children"
onChange={this.onChange}
onBlur={this.save}
labelInValue
filterOption={(input, option) =>
option.props.children
.toLowerCase()
.indexOf(input.toLowerCase()) >= 0
}
>
{tableFormData.map((item, index) => {
if (item.id.slice(-8) == connectFormData.nodeTargetId) {
return (
<Option key={index} value={index}>
{item.name}
</Option>
);
}
})}
</Select>
)}
</Form.Item>
);
}
};
render() {
const {
editable,
dataIndex,
title,
record,
index,
handleSave,
children,
...restProps
} = this.props;
return (
<td {...restProps}>
{editable ? (
<EditableContext.Consumer>{this.renderCell}</EditableContext.Consumer>
) : (
children
)}
</td>
);
}
}
class ConnectForm extends Component<ConnectFormProps, ConnectFormState> {
//补全类型1
tableRelationsData: {
key: string;
id: number;
mainTableId: string;
subTableId: string;
relationShip: number;
condition: number;
}[];
static defaultProps = {
handleUpdate: () => {},
handleConnectModalVisible: () => {},
values: {}
};
state = {
selectedRowKeys: [],
}
constructor(props: ConnectFormProps) {
super(props);
console.log(props.tableRelationsData)
this.columns = [
{
title: "主表字段",
dataIndex: "MainTablefield",
editable: true
},
{
title: "运算符",
dataIndex: "operator",
editable: true
},
{
title: "连接表字段",
dataIndex: "auxiliaryTablefield",
editable: true
},
{
title: "操作",
dataIndex: "operation",
render: (text, record) =>
this.state.dataSource.length >= 1 ? (
<Popconfirm
title="确定要删除?"
onConfirm={() => this.handleDelete(record.key)}
>
<a>删除</a>
</Popconfirm>
) : null
}
];
this.state = {
dataSource: [
{
key: "0",
value: "0",
text: "0"
}
],
count: 0,
dataSource2: [
{
key: "1",
value: "LEFT_JOIN",
text: "左连接"
},
{
key: "2",
value: "RIGHT_JOIN",
text: "右连接"
},
{
key: "3",
value: "INNER_JOIN",
text: "内连接"
},
{
key: "4",
value: "FULL_JOIN",
text: "全连接"
}
],
tableRelations: [
{
condition: "",
id: "",
main: {
aliasName: "",
id: "",
schema: "",
tableName: ""
},
relationShip: "",
sub: {
aliasName: "",
id: "",
schema: "",
tableName: ""
}
}
],
tablealiasName: {
mainTablealiasName: "",
auxiliaryTablealiasName: "",
mainNodeId: "",
auxiliaryNodeId: ""
},
TableconnectType: {
connectType: ""
},
tableModels: {
//用于保存ConnectForm 的tableModels对应关系
mainschema: "",
maintableName: "",
mainId: "",
auxiliaryschema: "",
auxiliarytableName: "",
auxiliaryId: ""
},
selectedRowKeys: selectedRowKeys,
};
// 回显编辑 ============ start ============
//拆分数据
this.nodeData = [];
this.notNodeData = [];
console.log('123==================>')
console.log(props.tableRelationsData)
props.tableRelationsData.forEach(item => {
if ((item.main.id === props.connectFormData.source.id)&&(item.sub.id === props.connectFormData.target.id)) {
console.log(item)
this.nodeData.push(item);
} else {
console.log(item)
this.notNodeData.push(item);
}
});
let selectedRowKeys = this.nodeData.map(item => item.id);
// 回显编辑 ============ end ============
}
GenNonDuplicateID = (randomLength: any) => {
return Number(
Math.random()
.toString()
.substr(3, randomLength) + Date.now()
).toString(36);
};
handleDelete = key => {
const dataSource = [...this.state.dataSource];
this.setState({ dataSource: dataSource.filter(item => item.key !== key) });
};
handleAdd = () => {
const { count, dataSource } = this.state;
const newData = {
key: this.state.count + 1,
value: this.state.count + 1,
text: this.state.count + 1
};
this.setState({
dataSource: [...dataSource, newData],
count: count + 1
});
};
handleSave = row => {
const newData = [...this.state.dataSource];
const index = newData.findIndex(item => row.key === item.key);
const item = newData[index];
newData.splice(index, 1, {
...item,
...row
});
this.setState({ dataSource: newData });
// console.log(this.state.dataSource);
};
okHandle = () => {
this.handleSave;
console.log(this.state);
console.log(this.state.dataSource);
const DataSourceForField = this.state.dataSource.filter(
item => item.MainTablefield
); //过滤,中留用户选择的字段
console.log(DataSourceForField);
//取出用户所选行字段,及关系符号
console.log(this.state.textArea); //连接方式 取值
this.state.textArea.map(item => {
this.state.TableconnectType.connectType = item.key;
});
const DataSourceForTableName = this.state.dataSource.filter(
item => item.mainTableTitle
); //过滤,保留主副表名及节点id
console.log(DataSourceForTableName);
const tableRelationsId = this.GenNonDuplicateID(12); //生成表关系 id
const tableRelationsList: any[] = [];
const userSaveAll = this.state.dataSource;
const userSelectJoin = this.state.textArea;
let userSelectJoinObj = {};
userSelectJoin.forEach(item => {
userSelectJoinObj["key"] = item.key;
userSelectJoinObj["value"] = item.value;
});
console.log(userSelectJoin);
userSaveAll.push(userSelectJoinObj); //将用户选择连接方式,转为对象,加入数组
userSaveAll.push(this.props.connectFormData); //加入表名,节点id
console.log(userSaveAll);
console.log(this.props.tableFormData);
//根据用户选择的两个节点值数据,分别 取出表的别名aliasName,节点id(表) nodeId
this.props.tableFormData.map((item, index) => {
// var mainTablealiasName;
if (item.id.slice(-8) == this.props.connectFormData.nodeSourceId) {
this.state.tablealiasName.mainTablealiasName = item.tableAliasName;
this.state.tablealiasName.mainNodeId = item.id;
} else if (item.id.slice(-8) == this.props.connectFormData.nodeTargetId) {
this.state.tablealiasName.auxiliaryTablealiasName = item.tableAliasName;
this.state.tablealiasName.auxiliaryNodeId = item.id;
}
});
console.log(this.state.tablealiasName);
//根据nodeId判断, 在 父组件传过来的 tableModelsData中 取出表的schema , tableName
this.props.tableModelsData.map((item, index) => { //tableModelsData中的id就是nodeId,不需要截取操作
if (item.id == this.props.connectFormData.nodeSourceId) {
this.state.tableModels.mainschema = this.props.connectFormData.mainSchemae;
this.state.tableModels.maintableName = this.props.connectFormData.mainTableTitle;
this.state.tableModels.mainId = this.props.connectFormData.nodeSourceId;
} else {
this.state.tableModels.auxiliaryschema = this.props.connectFormData.auxiliarySchema;
this.state.tableModels.auxiliarytableName = this.props.connectFormData.auxiliaryTableTitle;
this.state.tableModels.auxiliaryId = this.props.connectFormData.nodeTargetId;
}
});
console.log(this.state.tableModels);
DataSourceForField.map(item => {
console.log(item);
//提取用户实际设置关系的字段数据
const tableRelations = {
condition:
this.state.tablealiasName.mainTablealiasName +
"." +
item.MainTablefield.label +
" " +
item.operator.key +
" " +
this.state.tablealiasName.auxiliaryTablealiasName +
"." +
item.auxiliaryTablefield.label,
id: this.GenNonDuplicateID(12),
main: {
aliasName: this.state.tablealiasName.mainTablealiasName,
id: this.state.tableModels.mainId,
schema: this.state.tableModels.mainschema,
tableName: this.state.tableModels.maintableName
},
relationShip: this.state.TableconnectType.connectType,
sub: {
aliasName: this.state.tablealiasName.auxiliaryTablealiasName,
id: this.state.tableModels.auxiliaryId,
schema: this.state.tableModels.auxiliaryschema,
tableName: this.state.tableModels.auxiliarytableName
}
};
tableRelationsList.push(tableRelations);
});
console.log(tableRelationsList);
this.props.onAddConnectForm(tableRelationsList);
this.setState({
dataSource: [
{
key: "0",
value: "0",
text: "0"
}
]
});
this.props.CloseConnectModalVisible();
};
handleSelectChange = value => {
this.setState({ textArea: [value] });
console.log(this.state.textArea);
console.log(value);
// this.setState({relationShip: value})
// console.log(this.state.relationShip)
};
// handleSelectChange = value => {
// console.log(value);
// this.form.setFieldsValue({
// selectValue: `${value}`
// });
// };
handleCancel = e => {
console.log(e);
this.props.CloseConnectModalVisible();
};
render() {
const {
ConnectModalVisible,
onCancel: handleConnectModalVisible,
values,
connectFormData,
tableFormData,
tableModelsData,
// tableRelationsData
} = this.props;
let tableRelationsData = this.props.tableRelationsData.map(item => {
let data = JSON.parse(JSON.stringify(item));
data.key = data.id;
console.log(data)
return data;
});
console.log(tableRelationsData);
const { dataSource, dataSource2 } = this.state;
const components = {
body: {
row: EditableFormRow,
cell: EditableCell
}
};
const columns = this.columns.map(col => {
//console.log(col)
if (!col.editable) {
return col;
}
return {
...col,
onCell: record => ({
record,
editable: col.editable,
dataIndex: col.dataIndex,
title: col.title,
handleSave: this.handleSave,
connectFormData: connectFormData,
tableFormData: tableFormData,
tableRelationsData: tableRelationsData
})
};
});
return (
<Modal
width={1000}
destroyOnClose
title="设置连接组件"
visible={ConnectModalVisible}
onOk={this.okHandle}
onCancel={this.handleCancel}
// afterClose={() => handleConnectModalVisible()}
maskClosable={false}
cancelText={"重置"}
okText={"提交"}
>
<Form layout="vertical">
<Row>
<Col span={7}>
<Form.Item label="主表">
<Input disabled value={connectFormData.mainTableTitle} />
</Form.Item>
</Col>
<Col span={1}></Col>
<Col span={8}>
<Form.Item label="连接方式">
<Select
showSearch
placeholder="请选择连接方式"
optionFilterProp="children"
onChange={this.handleSelectChange}
// onBlur={this.save}
labelInValue
filterOption={(input, option) =>
option.props.children
.toLowerCase()
.indexOf(input.toLowerCase()) >= 0
}
>
{dataSource2.map(item => (
<Option key={item.value} value={item.value}>
{item.text}
</Option>
))}
{/* <Option value="1">右连接</Option>
<Option value="2">左连接</Option>
<Option value="3">全连接</Option> */}
</Select>
</Form.Item>
</Col>
<Col span={1}></Col>
<Col span={7}>
<Form.Item label="连接表">
<Input disabled value={connectFormData.auxiliaryTableTitle} />
</Form.Item>
</Col>
</Row>
<Form.Item label="连接条件">
<div id="components-table-demo-edit-cell">
<Button
onClick={this.handleAdd}
type="primary"
style={{ marginBottom: 16 }}
>
新增字段
</Button>
<Table
components={components}
rowClassName={() => "editable-row"}
bordered
dataSource={dataSource}
columns={columns}
/>
</div>
</Form.Item>
</Form>
</Modal>
);
}
}
export default Form.create<ConnectFormProps>()(ConnectForm);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
你的tableRelationsData是父组件setState动态赋值的吧?还是静态写死的?
constructor只会执行一次 之后props变化constructor不会在执行了 可以设置个key让组件卸载再装在试试
constructor 在整个生命周期内只会执行一次,如果此时参数没有更新的话,是拿不到新参数的。反复卸载组件确实可以拿到新参数,但是开销太大了,不建议使用。
既然用了类式组件,就要按照类式组件的规则来,尽可能地在组件生命周期内完成组件功能,这里推荐使用的生命周期钩子函数是getDerivedStateFromProps。
getDerivedStateFromProps 的第一个参数是父组件传入的 props ,第二个参数是子组件当前的 state,返回的参数作为新的 state 来渲染组件,返回 null 的话就不更新组件,这样可以节省 diff 和重新渲染的开销。
看了最新的文档,居然建议修改 key ,而不是复用组件!大概是因为有太多人动不动就创建一个类式组件,所以官方干脆默许这种写法了。