将基于React类的组件转换为功能组件

时间:2020-07-07 02:46:24

标签: javascript reactjs react-functional-component

我正在尝试将以下代码片段转换为使用基于功能的组件。

class IssueTable extends React.Component {
  constructor() {
    super();
    this.state = { issues: [] };
    setTimeout(() => {
      this.createIssue(sampleIssue);
    }, 2000);
  }

  componentDidMount() {
    this.loadData();
  }

  loadData() {
    setTimeout(() => {
      this.setState({ issues: initialIssues });
    }, 500);
  }

  createIssue(issue) {
    issue.id = this.state.issues.length + 1;
    issue.created = new Date();
    const newIssueList = this.state.issues.slice();
    newIssueList.push(issue);
    this.setState({ issues: newIssueList });
  }

  render() {
    const issueRows = this.state.issues.map(issue =>
      <IssueRow key={issue.id} issue={issue} />
    );

    return (
      <table className="bordered-table">
        <thead>
          <tr>
            <th>ID</th>
            <th>Status</th>
            <th>Owner</th>
            <th>Created</th>
            <th>Effort</th>
            <th>Due Date</th>
            <th>Title</th>
          </tr>
        </thead>
        <tbody>
          {issueRows}
        </tbody>
      </table>
    );
  }
}

在尝试将其转换为表格时,表格始终保持重新呈现状态,但我得到了关键的非唯一错误。我用过useEffect,但我不知道如何使用构造函数之类的功能。如何使用功能来实现它。 (issueRows是负责处理表中行数据的组件)。功能版本如下所示:

function IssueTable(){

  const [issue1, setIssues] = React.useState([]);

  React.useEffect(()=>{loadData()},[]);

    setTimeout(() => {
      createIssue(sampleIssue);
    }, 2000);
  


  function loadData() {
    setTimeout(() => {
      setIssues(issues);
    }, 500);
  }


  function createIssue(issue) {
    issue.id = issue1.length+1;
    issue.created = new Date();
    const newIssueList = issue1.slice();
    newIssueList.push(issue);
    setIssues(newIssueList);
    }
    

    
    const issueRows = issue1.map(issue =>
        <IssueRow key={issue.id} issue={issue} />
      )

    return <table className="bordered-table">
    <thead>
      <tr>
        <th>ID</th>
        <th>Status</th>
        <th>Owner</th>
        <th>Created</th>
        <th>Effort</th>
        <th>Due Date</th>
        <th>Title</th>
      </tr>
    </thead>
    <tbody>
      {issueRows}
    </tbody>
  </table>
}

function IssueRow(props){
    return(
        <tr>
            <td>{props.issue.id}</td>
            <td>{props.issue.status}</td>
            <td>{props.issue.owner}</td>
            <td>{props.issue.created.toDateString()}</td>
            <td>{props.issue.effort}</td>
            <td>{props.issue.due?props.issue.due.toDateString():""}</td>
            <td>{props.issue.title}</td>
        </tr>
    );
}

3 个答案:

答案 0 :(得分:1)

这应该在另一个private void checkVersion() { Observable<String> observable = Observable.fromCallable(new Callable<String>() { @Override public String call() throws Exception { String data = getHeadlines("https://play.google.com/store/apps/details?id=" + BuildConfig.APPLICATION_ID + "&hl=en"); return data; } }); } public String getHeadlines(String source) throws IOException { Document document = Jsoup.connect(source) .timeout(30000) .userAgent("Mozilla/5.0 (Windows; U; WindowsNT 5.1; en-US; rv1.8.1.6) Gecko/20070725 Firefox/2.0.0.6") .referrer("http://www.google.com") .get(); if (document != null) { Elements element = document.getElementsContainingOwnText("Current Version"); for (Element ele : element) { if (ele.siblingElements() != null) { Elements sibElemets = ele.siblingElements(); for (Element sibElemet : sibElemets) { newVersion = sibElemet.text(); } } } } return newVersion; } 里面:

React.useEffect()

否则,它将循环运行每个渲染。根据经验,在useEffect之外不应有任何副作用。

答案 1 :(得分:1)

查看此工作沙箱: https://codesandbox.io/s/confident-taussig-tg3my?file=/src/App.js

要注意的一件事是,您不应该基于线性序列[或索引]建立键,因为这可能会使React的跟踪混乱。取而代之的是,将索引值从map传递到IssueRow组件以跟踪顺序,并为每个问题提供自己的序列化ID。

 const issueRows = issues.map((issue, index) => (
    <IssueRow key={issue.id} issue={issue} index={index} />
  ));

另外,更新依赖于先前状态的状态的正确方法是传递函数而不是对象:

 setIssues(state => [...state, issue]);

您实质上是在迭代先前的状态,并添加新的问题。

答案 2 :(得分:0)

功能组件看起来像这样:

function IssueTable() {
  const [issue1, setIssues] = React.useState([]);
  const createIssue = React.useCallback(
    function createIssue(issue) {
      //passing callback to setIssues
      //  so useCallback does not depend
      //  on issue1 and does not have stale
      //  closure for issue1
      setIssues((issues) => {
        issue.id = issues.length + 1;
        issue.created = new Date();
        const newIssueList = issues.slice();
        newIssueList.push(issue);
        return newIssueList;
      });
    },
    []
  );
  React.useEffect(() => {
    setTimeout(() => {
      createIssue(sampleIssue);
    }, 2000);
  }, [createIssue]);
  React.useEffect(() => {
    setTimeout(() => {
      setIssues(initialIssues);
    }, 500);
  }, []);

  const issueRows = issue1.map((issue) => (
    <IssueRow key={issue.id} issue={issue} />
  ));

  return (
    <table className="bordered-table">
      <thead>
        <tr>
          <th>ID</th>
          <th>Status</th>
          <th>Owner</th>
          <th>Created</th>
          <th>Effort</th>
          <th>Due Date</th>
          <th>Title</th>
        </tr>
      </thead>
      <tbody>{issueRows}</tbody>
    </table>
  );
}