【问题标题】:React: Component with just a form, form submit action differs depending on consumer of the componentReact:只有一个表单的组件,表单提交操作因组件的使用者而异
【发布时间】:2020-01-16 14:07:18
【问题描述】:

我有一个显示简单搜索表单的 React 组件。我正在使用“受控组件”(https://reactjs.org/docs/forms.html),以便 React 组件存储搜索条件并且是事实的来源。

class SearchForm extends React.Component {    

    constructor(props) {
        super(props);
        this.state = {criteria: ''};    
        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }

    handleChange(event) {
        this.setState({criteria: event.target.value});
    }

    handleSubmit(event) {
        event.preventDefault();
        // only submit the search if there is search criteria
        if (this.state.criteria.length > 0){
            // I need to be able to set some state here
            this.setState({
                   .....
            });
            // i also need to access this.props here
            if (this.props......) ...
        }
    }

    render() {
        return (
            <form onSubmit={this.handleSubmit} >

                <input type="text" 
                       placeholder="Search"
                       value={this.state.criteria} 
                       onChange={this.handleChange} />

                <button ...... />
            </form>
        );
    }
}

我想在 2 个地方使用这个 SearchForm。

  • 标题中的搜索框:当表单提交时,它会重定向到我的应用程序中的另一个页面
  • 搜索页面上的搜索框:当表单提交时,它会更新搜索表单下方的搜索列表

因此,SearchForm 的 onSubmit 方法不能有代码来执行 onForm 提交,因为此代码将根据 SearchForms 的使用情况而有所不同。

我知道如何在我的组件 HTML 中添加搜索表单,例如在 Component1 的渲染方法中我会有

<div>
    <SearchForm />
</div>

但是,我不知道如何为使用搜索表单的每个组件以不同的方式处理 SearchForms onSubmit。就像我希望 SearchForm 的 onSubmit 调用包含组件中的方法,传递 SearchForm 的 state.criteria 值

如何在表单提交操作不同的其他组件中重用 SearchForm 组件?

【问题讨论】:

  • 只需将附加参数添加到您的组件&lt;SearchForm onSubmit={yourFunction} /&gt;,然后在您的handleSubmit 函数中调用它
  • 然后像这样在 handleSubmit 中调用你的函数:this.props.yourFunction()

标签: javascript reactjs forms


【解决方案1】:

我认为您可以将搜索表单转换为函数组件并将提交处理程序作为道具传递。在这里使用Hooks 将是一个理想的选择。


 import React, { useState } from "react";

    export function SearchForm(props) {
      const [search, setInput] = useState('');

      const handleSubmit = (evt) => {
          evt.preventDefault();
          //validation here
         props.onSubmit(search)
      }
      return (
        <form onSubmit={this.handleSubmit}>
         <input
          type="text"
           placeholder="Search"
           value={search}
           onChange={(event) => setInput(event.target.value)}
        />

   <button/>
</form>;

      );
    }

然后您可以在组件中使用此搜索表单,并执行所需的提交操作。

import React, { Component } from 'react'
import { Text, View } from 'react-native'

import React, { Component } from 'react'

export default class Header extends Component {

  constructor(props){
     super(props)
     this.state = {whatever: ''}
     this.onSearch = this.onSearch.bind(this)
   }

  onSearch(value){
   //you logic to navigate or display searched items
  }
  render() {
    return (
      <div>
        <SearchForm onSubmit={this.onSearch}>
      </div>
    )
  }
}


希望这会有所帮助。

【讨论】:

  • 这是非常棒的帮助,非常感谢。我有一个问题。在容器组件的 onSearch 中,您有“导航或显示搜索项目的逻辑”,我似乎无法访问我需要的组件状态。我已经更新了我原来的帖子,表明我需要在提交表单时访问 state 和 props
  • 啊,我知道我需要在包含组件中绑定函数,以便它可以访问“this”componentWillMount() { this.handleFormSubmit = this.handleFormSubmit.bind(this); }
  • @se22as 是的,需要绑定函数,但建议在构造函数中进行。也不推荐使用 componentWillMount。 reactjs.org/docs/handling-events.html。我已经更新了答案。
【解决方案2】:

你必须将回调函数作为props传递给你的组件,例如:


class SearchForm extends React.Component {    

    constructor(props) {
        super(props);
        this.state = {criteria: ''};    
        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }

    handleChange(event) {
        this.setState({criteria: event.target.value});
    }

    handleSubmit(event) {
        event.preventDefault();
        // only submit the search if there is search criteria
        if (this.state.criteria.length > 0){
            this.props.onFormSubmit()
        }
    }

    render() {
        return (
            <form onSubmit={this.handleSubmit} >

                <input type="text" 
                       placeholder="Search"
                       value={this.state.criteria} 
                       onChange={this.handleChange} />

                <button ...... />
            </form>
        );
    }
}

及组件用法:

<div>
  <SearchForm onFormSubmit={this.handleFormSubmit} />
</div>

【讨论】:

  • 谢谢你,这是很棒的帮助。我已经阅读了更多关于钩子的内容。我无法弄清楚的一件事是,在我包含组件的“handleFormSubmit”方法中,我无法访问组件状态或道具(即 this.props 或 this.state),控制台显示“this.setState 不是函数" 但是该代码之前运行良好。我已经更新了我原来的帖子,表明我需要在提交表单时访问 state 和 props
  • 啊,我知道我需要在包含组件中绑定函数,以便它可以访问“this”componentWillMount() { this.handleFormSubmit = this.handleFormSubmit.bind(this); }
  • 我只将另一个答案标记为正确,因为 Hooks 文档说您应该使用函数而不是类。
【解决方案3】:

我在此处添加更多信息,因为我需要做更多的事情来使我的代码正常工作。

上面的答案回答了我的问题,但是我必须为包含组件做一些额外的事情才能按照我的要求做,例如

  • SearchForm回调时访问组件中的“this”(即组件“handleFormSubmit”方法)
  • 在其中一种情况下在 SearchForm 的输入框中显示一个初始值(即在搜索结果页面上显示传递给它的条件)

使用 Hooks 定义为函数的可重用组件 (https://reactjs.org/docs/hooks-intro.html)

import React, { useState } from 'react';

export default function SearchForm (props) {   

    // if a value was passed into this component, use it as the initial search criteria
    const [searchCriteria, setSearchCriteria] = useState(props.value ? props.value : '');

    const handleSubmit = (evt) => {
        evt.preventDefault();

        if (searchCriteria.length > 0){
            props.onFormSubmit(searchCriteria)
        }
    }

    return (
        <form onSubmit={handleSubmit}>

            <input type="text" 
                   value={searchCriteria}
                   onChange={(event) => setSearchCriteria(event.target.value)}/>

            <button />
        </form>
    );
}

用法 1:标题中的搜索框:当表单提交时,它会重定向到“搜索结果页面”

import React from 'react';
import { withRouter} from 'react-router-dom';
import SearchForm from './SearchForm'

class SearchBox extends React.Component {

    componentDidMount() {
        // bind the SearchForm's callback method, so in "handleFormSubmit" we can use "this"
        this.handleFormSubmit = this.handleFormSubmit.bind(this);
    }

    handleFormSubmit(criteria){
        this.props.history.push('/searchresultspage/'+ criteria)
    }

    render() {
        return (
            <SearchForm onFormSubmit={this.handleFormSubmit} />
        );
    }
}

// The following is needed so that the "this.props.history.push" in "handleSumbit" causes routing to happen
export default withRouter(SearchBox)

用法二:搜索结果页面上的搜索框

  • 首次显示搜索结果页面时,其搜索框应包含传递给该页面的搜索条件(即从标题中的搜索框)
  • 应执行搜索并显示结果
  • 用户可以更改搜索框中的搜索词并执行新搜索

代码:

import React from 'react';

import SearchForm from './SearchForm'

export default class SearchResultsPage extends React.Component {

    state = {
        searchResults: [],
    }

    componentDidMount() {
        // bind the SearchForm's callback method, so in "handleFormSubmit" we can use "this"
        this.handleFormSubmit = this.handleFormSubmit.bind(this);

        this.performSearch(this.props.criteria);
    }

    handleFormSubmit(criteria){
        this.performSearch(criteria)
    }

    performSearch(criteria) {
        // do whatever to do a search and get results (e.g. store in this.state.searchResults)
    }


    render() {
        return (
            <div>
                {/* Pass the initial search criteria to the search form */}
                <SearchForm value={this.props.criteria} onFormSubmit={this.handleFormSubmit} />

                {/* do whatever to display the "this.state.searchResults */}
            </div>
        );
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-14
    • 2021-07-06
    • 1970-01-01
    • 2021-10-13
    • 2016-04-10
    • 1970-01-01
    • 2014-07-30
    • 2022-12-22
    相关资源
    最近更新 更多