0

I am fairly new to reactJS and I am wondering what's the best way to handle having the same form component on a single page. Please keep in mind that i am using flux and the component is talking to a store.

For example: < SearchForm /> < SearchForm />

When I try to use form #1 input field, Form #2 gets the value from form #1 at the same time. i think the problem is coming from the store. the components are speaking to the same store and the store is updating all the components at once.

How can i handle this problem?

here is the code i have so far.

const SearchField = React.createClass({

propTypes: {
    isSearchActivated: React.PropTypes.bool.isRequired,
},

_onChange() {
    var previousHighlightedIndex = this.state.highlightedIndex;
    this.setState(getStateFromStores(), function() {
        if (previousHighlightedIndex == 0 &&
                this.state.highlightedIndex == -1) {
            this.refs.SearchBar.selectAll();
        }
    });
},

componentDidMount() {
    if (window.location.pathname == "/" && !Modernizr.mq("screen only and (max-width: 768px)")) {
        $(ReactDOM.findDOMNode(this.refs.SearchBar)).find("input").focus();
    }
},

componentWillUnmount() {
    SearchResultStore.removeChangeListener(this._onChange);
},

onChangeSearchString(e) {
    SearchResultsUtils.search(e.target.value);
},

onBlur(e) {
    var self = this;
    var cb = function() {
        if (!self.state.selectedResult && self.state.results.length) {
            self.handleSelectedResult(0);
        }

        SearchResultsActions.disallowResultsDisplay();
    };
    if($(".search-bar").hasClass("active")) {
        $(".search-bar.active").removeClass("active");
    }
},

onFocus(e) {
    $(ReactDOM.findDOMNode(this.refs.SearchBar)).closest(".search-bar").addClass("active");
},

handleSubmit() {
    var self = this;
},

render() {
    var className = "search-bar clearfix";

    return (
        <div className={className}>
            <div className="search-bar-search">
                <SearchBar
                    searchString={this.state.searchString}
                    onChange={this.onChangeSearchString}
                    onKeyDown={this.onKeyDownSearchString}
                    onFocus={this.onFocus}
                    onBlur={this.onBlur}
                    placeholder="Search Meds or Conditions"
                    ref="SearchBar" />
            </div>

            <SearchButton
                handleSubmit={this.handleSubmit} />
        </div>
    );
},
});

module.exports = SearchField;

Thanks for the help in advance.

3
  • Can you add your code? Sounds like both forms share the same state. Commented Apr 11, 2016 at 15:38
  • If you really have plain <SearchForm/> <SearchForm/>, then react cannot cause form #2 to be updated when you enter something in form #1. Your tags also mention jQuery. Are you by any chance using jQuery to update the form? Then this is more likely the source of your issue. (And you really should not mix jQuery and react in this way). Could you add more code to your question? Commented Apr 11, 2016 at 16:07
  • i updated the question. Commented Apr 11, 2016 at 18:04

3 Answers 3

1

Definitely you can reuse your components multiple times across your application.

1.If you do not want to have any state:

In your situation you can provide form submit handler as callback prop. If you do not want to maintain any state on your search form. e.g For form 1

<Searchform submitHandler={searchForm1Handler}/>

For form 2

<Searchform submitHandler={searchForm2Handler}/> 

and Inside your search form component

render(){
  return (
     <form id="searchform" onSubmit={this.props.submitHandler} role="form">
      // other input and buttons
     </form>
   )
}

2. With states

With this approach each component will have its own separate states which will be private to them.

Here is sample component to illustrate this

import React ,{ Component } from 'react';

export default class SearchForm extends Component {

    constructor(props){
        super(props);
        this.state = {
            searchTerm : ''
        };
        this.submit = this.submit.bind(this);
        this.changeSearchTerm = this.changeSearchTerm.bind(this);
    }

    submit(e){

        e.preventDefault();

        let searchTerm = this.state.searchTerm;
        //Now perform some action based on search term you get
    }

    changeSearchTerm(e){
        this.setState({searchTerm :e.target.value});
    }

    render(){

        return(
            <div>
                <div className="row">
                  <div className="col-md-12">
                      <form role="form" className="form-horizontal" onSubmit={this.submit}>
                        <fieldset>
                          <div className="form-group">
                            <div className="col-sm-6">
                                <input id="st" type="text" placeholder="search term" onChange={this.changeSearchTerm} value={this.state.searchTerm} required autofocus/>
                            </div>
                         </div>
                         <div className="form-group">
                             <div className="col-xs-12 text-center">
                                 <button className="btn">
                                 Search
                                 </button>
                           </div>
                          </div>
                        </fieldset>
                      </form>
                  </div>
                </div>
            </div>
        )
    }
}

Now to use them

For form 1

<Searchform/>

For form 2

<Searchform/> 
Sign up to request clarification or add additional context in comments.

Comments

0

React has stateful components:

a component can maintain internal state data (accessed via this.state)

which allows you to have <SearchForm />#1 with value1, and <SearchForm />#2 with value2 stored in this.state

To build a form, check this: https://facebook.github.io/react/docs/forms.html

2 Comments

how would you set it ? can you give me an example code snippet please.
see @WitVault answer which is greate : stackoverflow.com/questions/36552422/…
0

It looks like your store only saves one state - which includes search value - for one form.
If you render this form twice, then both forms retrieve the same state on each change. So they are an exact copy of each other by design. If one form changes, both forms notice the change, and both forms will retrieve the exact same state from the store.

To fix this, I would suggest:

  • change the store so that it can save a state for multiple forms, each with its own ID
  • pass this ID to each form as a prop, e.g. <SearchForm formID='form1'/> <SearchForm formID='form2'/>
  • pass the formID down as a prop to all children of the form, such as <SearchField>
  • inside the <SearchField>, make sure your component only renders state from its own formID. You probably need to update the getStateFromStores() method itself. Or inside <SearchField> filter out relevant stuff first, before passing it to setState().
  • when your component informs the store that something has changed (I guess this is what SearchResultsUtils.search(e.target.value); does), then you need to pass the formID as well. So the store will know which form to update.

PS: I think your code is missing some lines in componentDidMount(): you have code to remove the listener to store changes, but your code to add the listener is missing. The code to invoke the _onChange() method is missing from your component.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.