React - 在 <option> 更新时更新 <select>
React - update <select> when <option> updated
我制作了一个简单的组件来填充 <select>
来自 REST 或本地数组的条目数组。代码使用如下:
<ComboBox id="TestAsync" label="Country List" default="DE" onChange={this.change}>
<DataSource source="/api/region/country" idField="id" captionField="name" />
</ComboBox>
<ComboBox>
基本上是用select的语句,但是用<DataSource>
检测。下面是<ComboBox>
渲染代码
constructor(props: IField) {
super(props);
this.state = {
value: props.default
}
}
public componentDidUpdate(prevProps: IField, prevStat: IState) {
if (prevProps.default != this.props.default) this.setState({ value: this.props.default });
}
render() {
return <div className="hx-field" id={this.props.id}>
<label>{this.props.label}</label>
<select name={this.props.id} onChange={this.onChangeSelect.bind(this)} value={this.state.value} disabled={this.props.readonly} key={this.props.id}>
{this.props.children}
</select>
</div>
}
这是 <Datasource>
class:
export class DataSource extends React.Component<IDataSource, IDataSourceState> {
constructor(props: IDataSource<T>) {
super(props);
this.state = {
rawData: null,
options: [
<option value="">Loading ... </option>
]
}
}
private option(item): JSX.Element {
return <option value={item[this.props.idField]} key={item[this.props.idField]}>{item[this.props.captionField]}</option>
}
private load() {
Adapter.load(this.props)
.then(result => {
if (!result) return;
this.setState({
rawData: result,
options: result.map(x => this.option(x))
})
})
.catch(error => {
console.error("DataSource load error: Cannot load REST data");
console.error(error);
})
}
public render() {
return this.state.options;
}
}
代码有效,但有一个例外。我无法向它发送默认值。我认为当 <select>
组件的值呈现时,数据源仍然是空的。但是当我在数据源填充后发送值时,代码工作正常。即从组合框中选择一个选项。
如何在 <datasource>
修改时强制更新 <select>
组件?
一种方法是在 <option>
:
上使用 selected
道具
export class DataSource extends React.Component<IDataSource, IDataSourceState> {
// ...
private option(item): JSX.Element {
const {idField, captionField} = this.props;
const {[idField]: id, [captionField]: caption} = item;
return
<option
value={id}
key={id}
selected={id===this.props.value}
>
{caption}
</option>
}
这样我们需要将实际的 value
传递给 DataSource
否则我们的默认值将永远不会改变:
<ComboBox id="TestAsync" label="Country List" onChange={this.changeCountryListValue}>
<DataSource source="/api/region/country" idField="id" captionField="name" selected={this.countryListValue || 'DE'} />
</ComboBox>
或者您可以通过注入 onLoad
回调或提供 selected
值来使 ComboBox
修改嵌套 DataSource
,就像我在上面以直接方式所做的那样。 React.children.map
和 React.cloneElement
to rescue on that.
最后,您可以将所有加载数据移出 ComboBox
到父元素或某些包装器。我宁愿遵循这种方式,因为目前您的通用命名 DataSource
将数据加载并将项目呈现到 <option>
中,这违反了单一责任原则。这可能不允许您在不同的上下文中使用它(当您需要加载相同的数据但显示在不同的组件而不是 <option>
)
我制作了一个简单的组件来填充 <select>
来自 REST 或本地数组的条目数组。代码使用如下:
<ComboBox id="TestAsync" label="Country List" default="DE" onChange={this.change}>
<DataSource source="/api/region/country" idField="id" captionField="name" />
</ComboBox>
<ComboBox>
基本上是用select的语句,但是用<DataSource>
检测。下面是<ComboBox>
渲染代码
constructor(props: IField) {
super(props);
this.state = {
value: props.default
}
}
public componentDidUpdate(prevProps: IField, prevStat: IState) {
if (prevProps.default != this.props.default) this.setState({ value: this.props.default });
}
render() {
return <div className="hx-field" id={this.props.id}>
<label>{this.props.label}</label>
<select name={this.props.id} onChange={this.onChangeSelect.bind(this)} value={this.state.value} disabled={this.props.readonly} key={this.props.id}>
{this.props.children}
</select>
</div>
}
这是 <Datasource>
class:
export class DataSource extends React.Component<IDataSource, IDataSourceState> {
constructor(props: IDataSource<T>) {
super(props);
this.state = {
rawData: null,
options: [
<option value="">Loading ... </option>
]
}
}
private option(item): JSX.Element {
return <option value={item[this.props.idField]} key={item[this.props.idField]}>{item[this.props.captionField]}</option>
}
private load() {
Adapter.load(this.props)
.then(result => {
if (!result) return;
this.setState({
rawData: result,
options: result.map(x => this.option(x))
})
})
.catch(error => {
console.error("DataSource load error: Cannot load REST data");
console.error(error);
})
}
public render() {
return this.state.options;
}
}
代码有效,但有一个例外。我无法向它发送默认值。我认为当 <select>
组件的值呈现时,数据源仍然是空的。但是当我在数据源填充后发送值时,代码工作正常。即从组合框中选择一个选项。
如何在 <datasource>
修改时强制更新 <select>
组件?
一种方法是在 <option>
:
selected
道具
export class DataSource extends React.Component<IDataSource, IDataSourceState> {
// ...
private option(item): JSX.Element {
const {idField, captionField} = this.props;
const {[idField]: id, [captionField]: caption} = item;
return
<option
value={id}
key={id}
selected={id===this.props.value}
>
{caption}
</option>
}
这样我们需要将实际的 value
传递给 DataSource
否则我们的默认值将永远不会改变:
<ComboBox id="TestAsync" label="Country List" onChange={this.changeCountryListValue}>
<DataSource source="/api/region/country" idField="id" captionField="name" selected={this.countryListValue || 'DE'} />
</ComboBox>
或者您可以通过注入 onLoad
回调或提供 selected
值来使 ComboBox
修改嵌套 DataSource
,就像我在上面以直接方式所做的那样。 React.children.map
和 React.cloneElement
to rescue on that.
最后,您可以将所有加载数据移出 ComboBox
到父元素或某些包装器。我宁愿遵循这种方式,因为目前您的通用命名 DataSource
将数据加载并将项目呈现到 <option>
中,这违反了单一责任原则。这可能不允许您在不同的上下文中使用它(当您需要加载相同的数据但显示在不同的组件而不是 <option>
)