通过单击按钮更新元素

时间:2019-06-21 15:17:17

标签: reactjs

一个很新的反应,并试图找出最好的方法来处理通过单击按钮更新自定义窗口小部件的方法。到目前为止,我有3个小部件-一个文本框,一个按钮和一个Twitter嵌入式供稿。在单击按钮后,我想基本上将Twitter feed更新为使用文本框中的输入重新呈现:

constructor(props){
      super(props)
      console.debug(props)
      this.state = {
        searchTerm: "test",
        selectedOption: null
      }
      this.onTextChange = this.onTextChange.bind(this);
      this.appChange = this.appChange.bind(this);
      this.searchClicked = this.searchClicked.bind(this);
    }

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

    appChange = selectedOption => {
      this.setState({ selectedOption });
      console.log('Option: ', selectedOption);
    }

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

render() {
        const { searchTerm } = this.state;


        return(
          <div>
            <div className="hashtag">
                <input name="search" type="text" className="textBox" placeholder={this.state.searchTerm} onInput={this.onTextChange}/>
                <br />
                <button id="btnSearch" className="searchBtn" onClick={this.searchClicked}>Search</button>
                <TwitterTimelineEmbed
                  sourceType="profile"
                  screenName={this.state.searchTerm}
                  options={{height:400, width: 400}}
                />
            </div>
          </div>
        );
    }
}

我尝试过使用componentDidUpate(),但未成功传递先前的道具/状态。

3 个答案:

答案 0 :(得分:1)

问题是,当您单击提交时,您将用e.target.value覆盖状态-这没什么,因为e.target是实际的提交按钮,而不是输入字段。

您不需要在setStatesearchClicked,因为每次按键(在onTextChange中)的状态都会更新。

我也删除了appChange,因为在此代码段中您不需要它。

解决方案要求您在key上添加<TwitterTimelineEmbed />,以便每当您要更新用户名时旧实例都会被销毁。

Twitter组件不允许您在状态更改时更新组件是一件好事,因为否则您可能很容易在每次重新渲染(很可能不是您想要的)时意外地调用Twitter API。 / p>

import React, { PureComponent } from "react";
import { TwitterTimelineEmbed } from "react-twitter-embed";

class Search extends PureComponent {
  constructor(props) {
    super(props);

    this.timelineId = 0; // initialize key

    this.state = {
      searchTerm: "TwitterEng"
    };

    this.onTextChange = this.onTextChange.bind(this);
    this.searchClicked = this.searchClicked.bind(this);
  }

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

  searchClicked(e) {
    // notice we removed the setState

    ++this.timelineId; // this is the key for the timelinefeed

    this.forceUpdate(); // you need to force update here if you want to update on search
  }

  render() {
    const { searchTerm } = this.state;

    return (
      <div>
        <div className="hashtag">
          <input
            name="search"
            type="text"
            className="textBox"
            placeholder={searchTerm}
            onInput={this.onTextChange}
          />
          <br />
          <button
            id="btnSearch"
            className="searchBtn"
            onClick={this.searchClicked}
          >
            Search
          </button>
          <TwitterTimelineEmbed
            key={this.timelineId}
            sourceType="profile"
            screenName={searchTerm}
            options={{ height: 400, width: 400 }}
          />
        </div>
      </div>
    );
  }
}

export default Search;

答案 1 :(得分:0)

所以我做了几件事可以解决您的问题。你已经很近了!

<input name="search" type="text" className="textBox" value={this.state.searchTerm} onChange={this.onTextChange}/>

首先,我根据您的输入将placeholder更改为value。这样可以使用户输入时正确更新输入字段。我还在此字段上将onInput更改为onChange。这样就可以触发更新功能了。

twitterOutput: ""

接下来,我为Twitter窗口添加了一个新的状态值。如果只希望在用户单击按钮时进行更新,则必须将其存储在单独的变量中。否则,当用户键入内容时,它也会自动绑定到Twitter窗口。如果这是您想要的行为,则可以在这里停止!

searchClicked(e){
  this.setState({
    twitterOutput: this.state.searchTerm
  })
}

<TwitterTimelineEmbed
  sourceType="profile"
  screenName={this.state.twitterOutput}
  options={{height:400, width: 400}}
/>

最后,我更改了click函数以更新您的新twitterOutput状态值,以便它可以更新您的时间轴,并更改了Twitter元素上的prop来反映这一点。

让我知道这是否有帮助!

完整代码:

constructor(props){
      super(props)
      console.debug(props)
      this.state = {
        searchTerm: "test",
        selectedOption: null,
        twitterOutput: ""
      }
      this.onTextChange = this.onTextChange.bind(this);
      this.appChange = this.appChange.bind(this);
      this.searchClicked = this.searchClicked.bind(this);
    }

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

    appChange = selectedOption => {
      this.setState({ selectedOption });
      console.log('Option: ', selectedOption);
    }

    searchClicked(e){
      this.setState({
        twitterOutput: this.state.searchTerm
      })
    }

render() {
        const { searchTerm } = this.state;


        return(
          <div>
            <div className="hashtag">
                <input name="search" type="text" className="textBox" value={this.state.searchTerm} onChange={this.onTextChange}/>
                <br />
                <button id="btnSearch" className="searchBtn" onClick={this.searchClicked}>Search</button>
                <TwitterTimelineEmbed
                  sourceType="profile"
                  screenName={this.state.twitterOutput}
                  options={{height:400, width: 400}}
                />
            </div>
          </div>
        );
    }
}

答案 2 :(得分:0)

您是否考虑过使用React hooks?这是带有React 16.8.6的codepen,可以解决您的问题。

import React, { useState} from 'react'
import ReactDOM from 'react-dom'

const App = () => {
  const [screenName, setScreenName] = useState('');
  const [goSearch, setGoSearch] = useState(false);

  const onChange = ({ target: { value } }) => {
    if(goSearch) setGoSearch(false);
    setScreenName(value);
  }

  const search = () => setGoSearch(true);

  return (
    <div className='hashtag'>
      <input 
        name='search' 
        type='text'
        className='textBox' 
        placeholder='Enter a twitter screen name' 
        onChange={onChange}
        value={screenName}
      />
      <br />
      <button 
        id='btnSearch'
        className='searchBtn ' 
        onClick={search}
      >
        Search
      </button>

      {/* This section is just for example */}
      {!!screenName && goSearch &&
        <p>You searched for <b>{screenName}</b></p>
      }

      {/* Uncomment this section to use with TwitterTimelineEmbed */}
      {/*goSearch && <TwitterTimelineEmbed
          sourceType="profile"
          screenName={screenName}
          options={{height:400, width: 400}}
        />*/}
    </div>
  )
}

ReactDOM.render(
  <App />,
  document.getElementById('root')
);

https://codepen.io/bflemi3/pen/mZWwYw

有多种方法可以实现此目的。我选择保留搜索词以及何时实际执行搜索。用户单击Search后,TwittterTimelineEmbed就会以更新的screenName作为prop呈现。