【问题标题】:Passing an attribute from a react component to a rails back end将属性从反应组件传递到 Rails 后端
【发布时间】:2017-08-03 14:26:22
【问题描述】:

我正在使用 webpacker 运行 React 和 Rails 5.2。

我在页面顶部有一个 ElasticSearch 搜索栏,我无法将正确的请求发送到后端,并且无法让 rails 后端处理搜索请求。

我们现在还没有准备好将其作为 SPA,但我似乎无法填充参数。

import React, {Component} from 'react';
import ReactDOM from 'react-dom';

import {asyncContainer, Typeahead} from 'react-bootstrap-typeahead';

const AsyncTypeahead = asyncContainer(Typeahead);

class SearchBar extends Component {


    constructor(props) {
        super(props)
        this.state = {
            options: ['Please Type Your Query'],
            searchPath: '/error_code/search',
            selected: [""],
        }

        this.handleSubmit = this.handleSubmit.bind(this);
        this.handleChange = this.handleChange.bind(this);
    }

    searchErrorCodes(term) {
        fetch(`/error_code/auto?query=${term}`)
            .then(resp => resp.json())
            .then(json => this.setState({options: json}))
    }


    handleChange(error_code_name) {
        let newValue = error_code_name

        this.setState({
            selected: newValue
        });

        this.setState({
            searchPath: `/error_code/search?error_code=${this.state.selected}`,
        });


        console.log(`This is the new searchPath is  ${this.state.searchPath}`);
    }

    handleSubmit(e) {
        alert(`submitted: ${this.state.selected}`);
        // event.preventDefault();
    }


    render() {

        return (
            <div>
                <form ref="form"
                      action={this.state.searchPath}
                      acceptCharset="UTF-8"
                      method="get"
                      onSubmit={e => this.handleSubmit(e)}
                >
                    <AsyncTypeahead
                        onSearch={term => this.searchErrorCodes(term)}
                        options={this.state.options}
                        className="search"
                        onClick={e => this.handleSubmit(e)}
                        selected={this.state.selected}
                        onChange={e => this.handleChange(e)}
                    />
                    <button
                        action={this.state.searchPath}
                        acceptCharset="UTF-8"
                        method="get"
                        type="submit"
                        className="btn btn-sm btn-search">
                        <i className="fa fa-search"></i>
                    </button>
                </form>
            </div>
        )
    }
}

ReactDOM.render(<SearchBar/>, document.querySelector('.search-bar'));

一切都正确渲染,但输入未正确发送到控制器。

【问题讨论】:

  • 当你触发this.setState({ searchPath: ``/error_code/search?error_code=${this.state.selected}``, });时,它会发送this.state.selected的旧值,而不是你刚才设置的那个?
  • 据我所知,它已更新,但当您单击提交时,表单按钮或其他内容不会传递该更新。它不向后端发送任何数据
  • 我会在你回答这个问题后添加到我的答案中。你是如何从onChange={e =&gt; this.handleChange(e)} 获得error_code_name 的?在这种情况下,内联 es6 箭头函数是无关的,也会导致性能问题并破坏浅层比较。
  • 它以数组的形式出现,里面有一个字符串
  • 您现在拥有它的方式是将error_code_name 设置为事件而不是输入的值。试试handleChange( e ) { let newValue = e.target.value; }

标签: javascript ruby-on-rails forms reactjs


【解决方案1】:

setState 本质上是异步的,短期内多次调用setState 会导致批量更新。意味着最后一次更新获胜。您的第二个 setState 调用覆盖了第一个。

将 setState() 视为更新组件的请求而不是立即命令。为了更好地感知性能,React 可能会延迟它,然后一次更新多个组件。 React 不保证立即应用状态更改。

考虑到您没有根据之前的状态或道具进行任何计算...您应该将 setState 调用更改为以下内容:

this.setState({
    selected: newValue,
    searchPath: `/error_code/search?error_code=${newValue}`
});

如果您需要前一个状态或道具来计算新状态,您也可以使用函数作为updatersetState(updater, [callback])

this.setState((prevState, props) => {
  return {counter: prevState.counter + props.step};
});

更新程序函数接收到的 prevState 和 props 都保证是最新的。 updater 的输出与 prevState 浅合并。

顺便说一句:请查看Why JSX props should not use arrow functions。内联使用它们是相当有害的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-18
    • 1970-01-01
    • 2018-04-28
    • 2021-03-12
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多