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

Javascript 将基于类的组件转换为功能组件,javascript,reactjs,react-functional-component,Javascript,Reactjs,React Functional Component,我试图将下面的代码片段转换为使用基于函数的组件 class IssueTable extends React.Component { constructor() { super(); this.state = { issues: [] }; setTimeout(() => { this.createIssue(sampleIssue); }, 2000); } componentDidMount() { this.load

我试图将下面的代码片段转换为使用基于函数的组件

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>
    );
  }
}
class IssueTable扩展了React.Component{
构造函数(){
超级();
this.state={issues:[]};
设置超时(()=>{
this.createIssue(sampleIssue);
}, 2000);
}
componentDidMount(){
这是loadData();
}
loadData(){
设置超时(()=>{
this.setState({issues:initialIssues});
}, 500);
}
创建问题(问题){
issue.id=this.state.issues.length+1;
issue.created=新日期();
const newIssueList=this.state.issues.slice();
newIssueList.push(发布);
this.setState({issues:newIssueList});
}
render(){
const issueRows=this.state.issues.map(issue=>
);
返回(
身份证件
地位
所有者
创建
努力
到期日
标题
{issueRows}
);
}
}
当试图转换它时,表不知何故一直在重新排序,我得到的键不是唯一的错误。我使用了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>
    );
}
函数IssueTable(){
const[issue1,setIssues]=React.useState([]);
React.useffect(()=>{loadData()},[]);
设置超时(()=>{
createIssue(sampleIssue);
}, 2000);
函数loadData(){
设置超时(()=>{
设置问题(问题);
}, 500);
}
函数createIssue(问题){
issue.id=issue1.length+1;
issue.created=新日期();
const newIssueList=issue1.slice();
newIssueList.push(发布);
setIssues(newIssueList);
}
const issueRows=issue1.map(issue=>
)
返回
身份证件
地位
所有者
创建
努力
到期日
标题
{issueRows}
}
功能发布程序(道具){
返回(
{props.issue.id}
{props.issue.status}
{props.issue.owner}
{props.issue.created.toDateString()}
{props.issue.efforce}
{props.issue.due?props.issue.due.toDateString():“”
{props.issue.title}
);
}

这应该在另一个
React.useffect()中。


否则,它将在循环中运行每个渲染。一般来说,除了useEffect之外,不应有任何副作用。

请查看此工作沙盒:

需要注意的一件事是,您不应该基于线性序列(或索引)的关键点,因为这可能会打乱React的跟踪。相反,将索引值从map传递到IssueRow组件以跟踪顺序,并为每个问题提供自己的序列化id

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

您基本上迭代了以前的状态,并添加了新问题。

功能组件可以如下所示:

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>
  );
}
函数IssueTable(){
const[issue1,setIssues]=React.useState([]);
const createIssue=React.useCallback(
函数createIssue(问题){
//将回调传递给setIssues
//所以useCallback不依赖于
//在问题1上,并且没有过时的
//问题1的关闭
设置问题((问题)=>{
issue.id=issues.length+1;
issue.created=新日期();
const newIssueList=issues.slice();
newIssueList.push(发布);
返回newIssueList;
});
},
[]
);
React.useffect(()=>{
设置超时(()=>{
createIssue(sampleIssue);
}, 2000);
},[createIssue]);
React.useffect(()=>{
设置超时(()=>{
设置问题(初始问题);
}, 500);
}, []);
const issueRows=issue1.map((问题)=>(
));
返回(
身份证件
地位
所有者
创建
努力
到期日
标题
{issueRows}
);
}

将功能版本放在此处,说明什么是
示例问题
问题
?它们从未在您的功能组件中定义。感谢您的回答!!我将setTimeout包装到一个函数中,然后在useEffect中调用它。它可以正常工作,没有任何错误,但问题是它不知何故失去了对数组issue1中先前数据的访问,只渲染了一行。请您调查一下,告诉我如何获取当前值,而不是使用陈旧数据。我不熟悉异步js,不知道如何处理它
 setIssues(state => [...state, issue]);
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>
  );
}