ReactJs不会在选择组件

时间:2016-05-09 22:25:15

标签: reactjs

我创建了一个自定义选择组件,当我从父级更新选项时,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);
			});

2 个答案:

答案 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>
			);			
	}
}