我创建了一个自定义选择组件,当我从父级更新选项时,render方法不会在select元素上重新呈现我的选项。
以下是我的代码:
选择组件:
render(){
return(
<select type='select'
multiple={this.props.isMultiSelect}
disabled={this.props.disabled}
value={this.props.value}
label={this.props.value}
items={this.props.items}
placeHolder={this.props.placeHolder}
onChange={this.handleChange} >
{() => {
if (this.props.items && this.props.items.length >0) {
this.props.items.map(this.renderSelectOption);
}
}}
</select>);
}
renderSelectOption(item){
return (
<option label={item.label} value={item.value}></option>
);
}
以下是使用items属性设置select组件的父组件,其中数据来自ajax请求:
Parent Component
<MySelect key={'templatesPickListKey'}
ref={'templatesPicklist'}
placeHolder={'Select Template...'}
items={this.state.myItems}
onChange={event => {this.setState({selectedTemplate: event.target.value});}}
isMultiSelect={false}
/>
我还有一个按钮,我只是用它来启动ajax请求并将数据返回给我的组件。我正在使用Promise实现,当它返回时它会改变我的状态。当我调试时,我看到了所有内容,当它进入select渲染方法时,似乎没有迭代思考这些项目。
以下是我为选择组件提出的建议。它有效,但我不确定我对状态和道具的使用是否遵循最佳实践,任何想法都将受到赞赏:
import React, {Component} from 'react';
export class MySelectComponent extends Component {
static propTypes = {
key: React.PropTypes.string,
isMultiSelect: React.PropTypes.bool.isRequired,
initialOptions: React.PropTypes.array,
onChange: React.PropTypes.func,
disabled: React.PropTypes.bool,
placeHolder: React.PropTypes.string,
value: React.PropTypes.string,
label: React.PropTypes.string
}
constructor(){
super();
this.state = {}
this.handleChange = this.handleChange.bind(this);
this.renderOptions = this.renderOptions.bind(this);
}
renderOptions() {
let options = [];
if (this.props.placeHolder) {
options.push(<option label={this.props.placeHolder} value=""></option>);
}
if (this.state.options) {
this.state.options.map(option => {
options.push(<option label={option.label} value={option.value}></option>);
});
} else if (this.props.initialOptions) {
this.props.initialOptions.map(option => {
options.push(<option label={option.label} value={option.value}></option>);
});
}
return options;
}
handleChange(event) {
if (typeof this.props.onChange === "function") {
this.props.onChange(event);
}
}
render() {
return(
<select type='select'
multiple={this.props.isMultiSelect}
disabled={this.props.disabled}
value={this.props.value}
label={this.props.value}
initialOptions={this.props.initialOptions}
placeHolder={this.props.placeHolder}
onChange={this.handleChange}
>
{this.renderOptions()}
</select>
);
}
}
以下是我将其包含在父组件中的方法:
<MySelectComponent key={'templatesPickListKey'}
ref={'templatesPicklist'}
placeHolder={'Select Template...'}
onChange={event => {this.setState({selectedTemplate: event.target.value});}}
isMultiSelect={false}
/>
This method makes a remote call and returns teh value by setState(args..) on my SelectComponent.
myPromise.then(result => {
let myOptions = [];
for (var key in result) {
myOptions.push({label: key, value: result[key]});
}
this.refs.templatesPicklist.setState({options: myOptions});
})
.catch(error => {
console.error("error: " + error);
});
答案 0 :(得分:0)
编辑:我注意到在你的例子中,函数名称没有对齐。您的自定义选择渲染使用this.handleChange
,但您的父级会传递onChange
。看起来你应该传下去了:
<MySelect handleChange={event => .. } />
以下表示法不正确:
{() => {
if (this.props.items && this.props.items.length >0) {
this.props.items.map(this.renderSelectOption);
}
}}
首先因为这是一个函数声明,而在JSX中你需要组件。
你可以在这里使用一个函数,只要你马上调用它......但是你还需要从调用map
返回数组。
{() => {
if (this.props.items && this.props.items.length > 0) {
return this.props.items.map(this.renderSelectOption); // added return
}
}()} <-- parens to invoke function (IIFE)
..但如果不使用函数表达式或if
语句,可以更简洁地编写:
{ this.props.items && // if exists
this.props.items.length > 0 && // if has length
this.props.items.map(this.renderSelectOption) // render array
}
您可以在调用map
之前添加默认值来进一步打高尔夫球:
{ (this.props.items || []).map(this.renderSelectOption) }
<强> FIDDLE 强>
答案 1 :(得分:-1)
所以下面的内容对我有用:
import React, {Component} from 'react';
export class MySelectComponent extends Component {
static propTypes = {
key: React.PropTypes.string,
isMultiSelect: React.PropTypes.bool.isRequired,
initialOptions: React.PropTypes.array,
onChange: React.PropTypes.func,
disabled: React.PropTypes.bool,
placeHolder: React.PropTypes.string,
value: React.PropTypes.string,
label: React.PropTypes.string
}
constructor(){
super();
this.state = {}
this.handleChange = this.handleChange.bind(this);
this.renderOptions = this.renderOptions.bind(this);
}
renderOptions() {
let options = [];
if (this.props.placeHolder) {
options.push(<option label={this.props.placeHolder} value=""></option>);
}
if (this.state.options) {
this.state.options.map(option => {
options.push(<option label={option.label} value={option.value}></option>);
});
} else if (this.props.initialOptions) {
this.props.initialOptions.map(option => {
options.push(<option label={option.label} value={option.value}></option>);
});
}
return options;
}
handleChange(event) {
if (typeof this.props.onChange === "function") {
this.props.onChange(event);
}
}
render() {
return(
<select type='select'
multiple={this.props.isMultiSelect}
disabled={this.props.disabled}
value={this.props.value}
label={this.props.value}
initialOptions={this.props.initialOptions}
placeHolder={this.props.placeHolder}
onChange={this.handleChange}
>
{this.renderOptions()}
</select>
);
}
}