反应嵌套数组
React Nested Array
我需要能够将其合并为一个功能。有 2 个独立的数组...
{this.state.telephoneType.map((telephoneType, ttidx) => ())}
和...
{this.state.telephone.map((telephone, tidx) => ())}
基本上,这是因为我有一个连接两个函数的按钮,它必须在行 class (MDBRow) 之外,所以 UI 不会中断。
<MDBRow className="grey-text no-gutters my-2">
{this.state.telephoneType.map((telephoneType, ttidx) => (
<MDBCol md="4" className="mr-2">
<select
key={ttidx}
defaultValue={telephoneType.name}
onChange={this.handleTelephoneTypeChange(ttidx)}
className="browser-default custom-select">
<option value="Mobile">Mobile</option>
<option value="Landline">Landline</option>
<option value="Work">Work</option>
</select>
</MDBCol>
))}
{this.state.telephone.map((telephone, tidx) => (
<MDBCol md="7" className="d-flex align-items-center">
<input
value={telephone.name}
onChange={this.handleTelephoneChange(tidx)}
placeholder={`Telephone No. #${tidx + 1}`}
className="form-control"
/>
<MDBIcon icon="minus-circle"
className="mr-0 ml-2 red-text"
onClick={this.handleRemoveTelephone(tidx)} />
</MDBCol>
))}
</MDBRow>
<div className="btn-add" onClick={this.handleAddTelephone}>
<MDBIcon className="mr-1" icon="plus-square" />
Add Telephone
</div>
这是 handleAddTelephone 函数...
handleAddTelephone = () => {
this.setState({
telephone: this.state.telephone.concat([{ name: "" }]),
telephoneType: this.state.telephoneType.concat([{ name: "" }])
});
};
构造器看起来像这样...
class InstallerAdd extends React.Component {
constructor() {
super();
this.state = {
role: "Installer",
name: "",
telephoneType: [{ name: "" }],
telephone: [{ name: "" }],
tidx: "",
emailType: [{ email: "" }],
email: [{ email: "" }],
eidx: "",
notes: ""
};
}
}
我可以将一个数组嵌套在另一个数组中吗?我不确定如何做到这一点,所以任何建议表示赞赏。谢谢。
编辑:
这些是需要 1 个功能的 2 个电话功能......
我已经为每个
更新了新的嵌套数组
handleTelephoneChange = tidx => evt => {
const newTelephone = this.state.telephone.type.map((telephone, tsidx) => {
if (tidx !== tsidx) return telephone;
return { ...telephone, name: evt.target.value };
});
this.setState({ telephone: newTelephone }, () => {
// get state on callback
console.log(this.state.telephone.number[tidx].name)
}
);
};
handleTelephoneTypeChange = ttidx => evt => {
const newTelephoneType = this.state.telephone.number.map((telephoneType, ttsidx) => {
if (ttidx !== ttsidx) return telephoneType;
return { ...telephoneType, name: evt.target.value };
});
this.setState({ telephoneType: newTelephoneType }, () => {
// get state on callback
console.log(this.state.telephone.type[ttidx].name)
}
);
};
我的构造函数现在看起来像这样...
class InstallerAdd extends React.Component {
constructor() {
super();
this.state = {
role: "Installer",
name: "",
telephone: {
type: [{ name: "" }],
number: [{ name: "" }]
},
tidx: "",
emailType: [{ email: "" }],
email: [{ email: "" }],
eidx: "",
notes: ""
};
}
是的,当然,还有一些东西:
telephone: {
list: [1,2,3],
type: [“foo”, “bar”, “baz”]
}
虽然我还是不太明白你的UI "breaks"(我无法加载视频),但希望能帮到你。
基本上,关于尝试单独映射两个数组的简短回答是你不能(好吧,不应该),但是有一些关于两个数组的长度总是相等的假设并且顺序两者之间是相同的,那么您可以映射第一个数组并使用映射函数中传递的 index
来访问第二个数组。
arrayA.map((itemFromA, index) => {
// do stuff with item from A
const itemFromB = arrayB[index];
// do stuff with item from B
});
我认为更好的解决方案是首先只保留一个数组以进行映射。
state = {
telephones: [], // { type: string, number: string }[]
}
...
state.telephones.map(({ type, number }, index) => {
// do stuff with telephone type
...
// do stuff with telephone number
});
如果你也真的想要只一个单独的更改处理程序(我建议它们分开),你可以采用redux action/reducer 接受对象作为参数的类型处理程序,该对象具有更新数组条目所需的所有数据(索引、更新类型、值)。这是一个非常简洁的示例,但在调用时需要一些 "action" 设置:
changeHandler = (index, type) => e => {
const newTelephoneData = [...this.state.telephones];
newTelephoneData[index][type] = e.target.value;
this.setState({ telephones: newTelephoneData });
}
<select
value={type}
onChange={this.telephoneChangeHandler(index, "type")}
>
// options
</select>
...
<input
value={number}
onChange={this.telephoneChangeHandler(index, "number")}
placeholder={`Telephone No. #${index + 1}`}
/>
下面我创建了一些工作沙盒演示:
- 双电话数据数组,单个更改 ("action/reducer") 处理程序,单独的 add/remove 函数,使用索引访问器的单个映射传递到第二个数组:
- 单个电话数据数组,单个更改处理程序,单独 add/remove,单个地图传递:
- 使用 react
useReducer
,单数组,reducer handles add/remove/update,单 map pass:
我已经包含了代码文档,但如果有任何不清楚的地方请告诉我,我可以清理这些演示。
我需要能够将其合并为一个功能。有 2 个独立的数组...
{this.state.telephoneType.map((telephoneType, ttidx) => ())}
和...
{this.state.telephone.map((telephone, tidx) => ())}
基本上,这是因为我有一个连接两个函数的按钮,它必须在行 class (MDBRow) 之外,所以 UI 不会中断。
<MDBRow className="grey-text no-gutters my-2">
{this.state.telephoneType.map((telephoneType, ttidx) => (
<MDBCol md="4" className="mr-2">
<select
key={ttidx}
defaultValue={telephoneType.name}
onChange={this.handleTelephoneTypeChange(ttidx)}
className="browser-default custom-select">
<option value="Mobile">Mobile</option>
<option value="Landline">Landline</option>
<option value="Work">Work</option>
</select>
</MDBCol>
))}
{this.state.telephone.map((telephone, tidx) => (
<MDBCol md="7" className="d-flex align-items-center">
<input
value={telephone.name}
onChange={this.handleTelephoneChange(tidx)}
placeholder={`Telephone No. #${tidx + 1}`}
className="form-control"
/>
<MDBIcon icon="minus-circle"
className="mr-0 ml-2 red-text"
onClick={this.handleRemoveTelephone(tidx)} />
</MDBCol>
))}
</MDBRow>
<div className="btn-add" onClick={this.handleAddTelephone}>
<MDBIcon className="mr-1" icon="plus-square" />
Add Telephone
</div>
这是 handleAddTelephone 函数...
handleAddTelephone = () => {
this.setState({
telephone: this.state.telephone.concat([{ name: "" }]),
telephoneType: this.state.telephoneType.concat([{ name: "" }])
});
};
构造器看起来像这样...
class InstallerAdd extends React.Component {
constructor() {
super();
this.state = {
role: "Installer",
name: "",
telephoneType: [{ name: "" }],
telephone: [{ name: "" }],
tidx: "",
emailType: [{ email: "" }],
email: [{ email: "" }],
eidx: "",
notes: ""
};
}
}
我可以将一个数组嵌套在另一个数组中吗?我不确定如何做到这一点,所以任何建议表示赞赏。谢谢。
编辑: 这些是需要 1 个功能的 2 个电话功能...... 我已经为每个
更新了新的嵌套数组handleTelephoneChange = tidx => evt => {
const newTelephone = this.state.telephone.type.map((telephone, tsidx) => {
if (tidx !== tsidx) return telephone;
return { ...telephone, name: evt.target.value };
});
this.setState({ telephone: newTelephone }, () => {
// get state on callback
console.log(this.state.telephone.number[tidx].name)
}
);
};
handleTelephoneTypeChange = ttidx => evt => {
const newTelephoneType = this.state.telephone.number.map((telephoneType, ttsidx) => {
if (ttidx !== ttsidx) return telephoneType;
return { ...telephoneType, name: evt.target.value };
});
this.setState({ telephoneType: newTelephoneType }, () => {
// get state on callback
console.log(this.state.telephone.type[ttidx].name)
}
);
};
我的构造函数现在看起来像这样...
class InstallerAdd extends React.Component {
constructor() {
super();
this.state = {
role: "Installer",
name: "",
telephone: {
type: [{ name: "" }],
number: [{ name: "" }]
},
tidx: "",
emailType: [{ email: "" }],
email: [{ email: "" }],
eidx: "",
notes: ""
};
}
是的,当然,还有一些东西:
telephone: {
list: [1,2,3],
type: [“foo”, “bar”, “baz”]
}
虽然我还是不太明白你的UI "breaks"(我无法加载视频),但希望能帮到你。
基本上,关于尝试单独映射两个数组的简短回答是你不能(好吧,不应该),但是有一些关于两个数组的长度总是相等的假设并且顺序两者之间是相同的,那么您可以映射第一个数组并使用映射函数中传递的 index
来访问第二个数组。
arrayA.map((itemFromA, index) => {
// do stuff with item from A
const itemFromB = arrayB[index];
// do stuff with item from B
});
我认为更好的解决方案是首先只保留一个数组以进行映射。
state = {
telephones: [], // { type: string, number: string }[]
}
...
state.telephones.map(({ type, number }, index) => {
// do stuff with telephone type
...
// do stuff with telephone number
});
如果你也真的想要只一个单独的更改处理程序(我建议它们分开),你可以采用redux action/reducer 接受对象作为参数的类型处理程序,该对象具有更新数组条目所需的所有数据(索引、更新类型、值)。这是一个非常简洁的示例,但在调用时需要一些 "action" 设置:
changeHandler = (index, type) => e => {
const newTelephoneData = [...this.state.telephones];
newTelephoneData[index][type] = e.target.value;
this.setState({ telephones: newTelephoneData });
}
<select
value={type}
onChange={this.telephoneChangeHandler(index, "type")}
>
// options
</select>
...
<input
value={number}
onChange={this.telephoneChangeHandler(index, "number")}
placeholder={`Telephone No. #${index + 1}`}
/>
下面我创建了一些工作沙盒演示:
- 双电话数据数组,单个更改 ("action/reducer") 处理程序,单独的 add/remove 函数,使用索引访问器的单个映射传递到第二个数组:
- 单个电话数据数组,单个更改处理程序,单独 add/remove,单个地图传递:
- 使用 react
useReducer
,单数组,reducer handles add/remove/update,单 map pass:
我已经包含了代码文档,但如果有任何不清楚的地方请告诉我,我可以清理这些演示。