在React JS中创建元素

我正在为react.js中的web-app重写UI,我对以下问题感到有些困惑。

我有一个页面显示通过AJAX请求获得的数据,在下面显示一个提交新数据的表单。 都好。

现在,我想在表单中添加一个元素,并从另一个位置(url)获取值。

当前代码(没有 )看起来像这样(简化了一下,但所有工作细节都相同;它主要遵循react.js网站上的教程):

 var tasks_link = $('#tasks_link'); var getDataMixin = { loadDataFromServer: function() { $.ajax({ url: this.props.url, dataType: 'json', success: function(data) { this.setState({data: data}); }.bind(this), error: function(xhr, status, err) { console.error(this.props.url, status, err.toString()); }.bind(this) }); }, getInitialState: function() { return {data: []}; }, componentDidMount: function() { this.loadDataFromServer(); } }; var sendDataMixin = { handleDataSubmit: function(senddata) { $.ajax({ url: this.props.url, dataType: 'json', contentType: 'application/json', type: 'POST', data: senddata, success: function(data) { var curr_d = this.state.data; var curr_d_new = curr_d.concat([data]); this.setState({data: curr_d_new}); }.bind(this), error: function(xhr, status, err) { console.error(this.props.url, status, err.toString()); }.bind(this) }); } }; var taskForm = React.createClass({ handleSubmit: function() { var name = this.refs.task_name.getDOMNode().value.trim(); if (!name) { return false; } this.props.onTaskSubmit(JSON.stringify({name: name})); this.refs.task_name.getDOMNode().value = ''; return false; }, render: function () { return ( 
Task name
); } }); var taskBox = React.createClass({ mixins: [getDataMixin, sendDataMixin], render: function () { return (
); } }); tasks_link.click(function() { React.renderComponent( , document.getElementById('content_container') ); });

现在,我可以通过向getDataMixin添加getDataMixin来添加一个select元素,获取数据并构建可能的选项列表,但是我需要有多个列表的表单,并且这种方法似乎没有扩展(由于命名碰撞;或者我需要使用除mixins之外的其他东西)。

所以我想创建一个单独的React class ,它只有getDataMixin ,通过父设置它的props接收API url,并渲染元素; 并在表单中使用此类。 但我不知道如何访问所选值(因为父母无法访问它的孩子的refs )。 所以我需要另一种方法来传递所选值“up”。

或者,如果这是不可能的,在正确的方向轻推 – 我不想最终得到大量不可重用的代码(我切换到反应的部分原因是使用mixins并保持代码到理智和可读的最小值)。

只要您将子项设置为父项中的ref,父项就可以访问其子项的引用,您可以访问该子项中的任何引用。 例如像this.refs.childRef.refs.nestedChildRef这样的东西。 然而,这是一个非常糟糕的主意,除非您只是阅读信息(并处理错误,例如引用不正确,因为父级不知道子级的ref是否设置正确)。

但幸运的是,有一个非常简单的解决方案。 你是对的,你会想要创建一个子组件来获取它自己的数据,而不是mixin。 但是如何处理将所选项目返回给父项只是简单地从父项传递onChange函数,就像你在内部的 in react一样。

以下是此父子关系的示例:

 var MyParent = React.createClass({ getInitialState: function() { return { childSelectValue: undefined } }, changeHandler: function(e) { this.setState({ childSelectValue: e.target.value }) }, render: function() { return ( 
) } }); var MySelect = React.createClass({ propTypes: { url: React.PropTypes.string.isRequired }, getInitialState: function() { return { options: [] } }, componentDidMount: function() { // get your data $.ajax({ url: this.props.url, success: this.successHandler }) }, successHandler: function(data) { // assuming data is an array of {name: "foo", value: "bar"} for (var i = 0; i < data.length; i++) { var option = data[i]; this.state.options.push( ); } this.forceUpdate(); }, render: function() { return this.transferPropsTo( ) } });

上面的示例显示了一个父组件MyParent ,它包含一个子组件MySelect ,它传递一个url,以及对标准react 元素有效的任何其他props。 使用this.transferPropsTo()函数中内置的this.transferPropsTo()将所有道具转移到其渲染函数中的子元素的元素。

这意味着定义changeHandler作为MySelectonChange处理程序的父changeHandler将此函数直接传递给子级的元素。 因此,当select更改时,事件将由父级而不是子级处理。 顺便说一句,这是在React中做事的完美合法和合法的方式 – 因为它仍然遵循自上而下的哲学。 如果您考虑一下,当您使用正常的内置 from react时,这正是正在发生的事情。 onChange只是一个属性。

值得注意的是,如果您愿意,可以“混合”更改处理程序以添加您自己的自定义逻辑。 例如,我倾向于使用自定义输入组件包装我的字段,该组件接受任何和所有有效的道具,但也将validator函数作为允许我定义的属性根据输入到字段的值返回true / false的函数。 我可以通过在父对象中为包装子定义onChange来做到这一点,但是在子this.props.onChange我在内部定义了我自己的onChange ,它检查要定义的this.props.onChange和一个函数,然后运行我的validation器并传递事件链通过调用this.props.onChange(e, valid)备份到父级。 在父类的onChange处理程序中给父元素提供相同的事件对象,但也添加了一个布尔valid参数。 无论如何,我离题….

希望这可以帮助你 :)