【问题标题】:Reactjs displaying Uncaught Error when trying to display dataReactjs在尝试显示数据时显示未捕获的错误
【发布时间】:2017-10-07 18:37:46
【问题描述】:

我正在尝试从头开始编写 reactjs 分页,但由于以下错误而陷入困境。

1.) Reactjs 在尝试显示数据库中的记录时显示以下错误 “未捕获的 TypeError:无法读取未定义的属性 'setState'”

2.) 当我点击页面链接时,它显示 "Uncaught ReferenceError: displayRecords is not defined 在 HTMLAnchorElement.onclick"。似乎 displayRecords() 函数没有很好地定义或绑定在下面的 javascript 中。

3.) 当我点击下拉链接时,它显示 "Uncaught ReferenceError: changeDisplayRowCount is not defined 在 HTMLSelectElement.onchange"。似乎 changeDisplayRowCount() 函数没有很好地定义或绑定在下面的 javascript 中。

请有人运行脚本并帮助我解决问题。至少即使它只是第一个错误(“Uncaught TypeError: Cannot read property 'setState' of undefined”)。

<script src="build/react.min.js"></script>
<script src="build/react-dom.min.js"></script>
<script src="build/browser.min.js"></script>
<script src="build/jquery.min.js"></script>


<a href="javascript:void(0);" class="links"  onclick="displayRecords('10', '1');" >Page</a>
<label> Rows Limit: 
<select name="show" onChange="changeDisplayRowCount(this.value);">
  <option value="10" >10</option>
  <option value="20" >20</option>
  <option value="30" >30</option>
</select>
</label>
<div id="root"></div>
<script type="text/babel">

class NameForm extends React.Component {
  constructor() {
    super();
    this.state = {
      data: []
    };
  }
  componentDidMount() {
    function displayRecords(numRecords, pageNum) {
      var show = numRecords;
      var pagenum = pageNum;

      alert(show);

      $.ajax({
        type: 'GET',
        url: 'getrecords.php',
        data: {
          show: numRecords,
          pagenum: pageNum
        },
        cache: false,
        success: function(data) {
          show: numRecords;
          pagenum: pagenum;

          $('#display')
            .html(data)
            .show();

          //console.log(email);

          console.log(show);
          console.log(pagenum);

          this.setState({data: data});
        }.bind(this),
        error: function(jqXHR) {
          console.log(jqXHR);
        }.bind(this)
      });
    } // end displayRecords

    function changeDisplayRowCount(numRecords) {
      displayRecords(numRecords, 1);
    }

    $(document).ready(function() {
      displayRecords(10, 1);
    });
  }

  render() {
    return (
      <div>
        {this.state.data ? (
          <div dangerouslySetInnerHTML={{__html: this.state.data}} />
        ) : (
          <div>Loading...</div>
        )}
      </div>
    );
  }
}
ReactDOM.render(
  <NameForm />,
  document.getElementById('root')
);


</script>

getrecords.php

<?php

echo $page = $_GET['pagenum'];
echo $show = $_GET["show"];

// pagination
?>

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:
    1. 您引用的函数displayRecords 不在页面的全局范围内,它在componentDidMount 中定义,您的HTML 标记无法使用该函数。
    2. select 标记在 label 标记内无效。
    3. 您同时使用 HTML 和 React,为什么?
    4. 您将this 绑定在一个未绑定的函数中,其中this 解析为根范围,这就是未定义setState 的原因。
    5. 您正在使用 jquery 设置标签的内部 HTML 而没有反应...为什么?
    6. 你正在使用dangerouslySetInnerHTML,你不应该使用,有更好的方法。
    7. 您正在从 React 组件中调用 $(document).ready ... 如果组件已安装,则文档已准备就绪,这是不需要的逻辑。

    以下是针对您的问题的直接解决方法:

    <script src="build/react.min.js"></script>
    <script src="build/react-dom.min.js"></script>
    <script src="build/browser.min.js"></script>
    <script src="build/jquery.min.js"></script>
    
    
    <a href="javascript:void(0);" class="links"  onclick="displayRecords('10', '1');" >Page</a>
    <label> Rows Limit: 
    <select name="show" onChange="changeDisplayRowCount(this.value);">
      <option value="10" >10</option>
      <option value="20" >20</option>
      <option value="30" >30</option>
    </select>
    </label>
    <div id="root"></div>
    <script type="text/babel">
    window.displayRecords = function(){
        alert('Component not mounted yet.');
    };
    
    window.changeDisplayRowCount = function(){
        alert('Component not mounted yet.');
    }
    class NameForm extends React.Component {
      constructor() {
        super();
        this.state = {
          data: []
        };
      }
      componentDidMount() {
        window.displayRecords = (function displayRecords(numRecords, pageNum) {
          var show = numRecords;
          var pagenum = pageNum;
    
          alert(show);
    
          $.ajax({
            type: 'GET',
            url: 'getrecords.php',
            data: {
              show: numRecords,
              pagenum: pageNum
            },
            cache: false,
            success: function(data) {
              show: numRecords;
              pagenum: pagenum;
    
              $('#display')
                .html(data)
                .show();
    
              //console.log(email);
    
              console.log(show);
              console.log(pagenum);
    
              this.setState({data: data});
            }.bind(this),
            error: function(jqXHR) {
              console.log(jqXHR);
            }.bind(this)
          });
        }.bind(this) // end displayRecords
    
        window.changeDisplayRowCount = function changeDisplayRowCount(numRecords) {
          displayRecords(numRecords, 1);
        }
    
        $(document).ready(function() {
          displayRecords(10, 1);
        });
      }
    
      render() {
        return (
          <div>
            {this.state.data ? (
              <div dangerouslySetInnerHTML={{__html: this.state.data}} />
            ) : (
              <div>Loading...</div>
            )}
          </div>
        );
      }
    }
    ReactDOM.render(
      <NameForm />,
      document.getElementById('root')
    );
    
    
    </script>
    

    虽然这将解决您的问题(或者应该如此),但您的代码应该如下所示:

    function PageLink({page,onClick}){
      return <div className="pageLink" onClick={onClick.bind(null,page)}>
        {page}
      </div>;
    }
    
    function RowSelector({selected,onChange}){
      return (
        <div className="rowSelector">
          <label>Rows Limit:</label>
          <select onChange={(e) => onChange(e.target.value)} value={selected}>
              {[10,20,30].map(num => <option key={num} value={num}>{num}</option>)}
          </select>
        </div>
      )
    }
    
    function DataItem({item}){
      // Assumes data is a map with a name key.
      return <div>{item.name}</div>;
    }
    
    class Pagination extends React.Component {
      constructor(props){
        super(props);
        this.state = {
          currentPage: 0,
          rowLimit: 10,
          data: [],
          loading: false
        };
        this.setCurrentPage = this.setCurrentPage.bind(this);
        this.setRowLimit = this.setRowLimit.bind(this);
      }
    
      updateData(){
        this.setState({loading: true});
        // This is just for mock purposes, remove this and use the ajax logic below.
        setTimeout(() => {
          this.setState({
            loading: false,
            data: (function(rowLimit){
              let res = [];
              for(let i = 0; i < rowLimit; i++){
                res.push({name: String(i)});
              }
              return res;
            })(this.state.rowLimit)
          })
        },1000);
        return;
        $.ajax({
          type: 'GET',
          url: 'getrecords.php',
          data: {
            show: this.state.rowLimit,
            pagenum: this.state.currentPage
          },
          cache: false,
          success: data =>  this.setState({data,loading: false}),
          error: jqXHR => {
            this.setState({loading:false});
            console.log(jqXHR);
          }
        });
      }
    
      componentDidUpdate(prevProps,prevState){
        if(this.state.currentPage != prevState.currentPage || this.state.rowLimit != prevState.rowLimit){
          this.updateData();
        }
      }
    
      componentDidMount(){
        this.updateData();
      }
    
      setCurrentPage(currentPage){
        this.setState({currentPage});
      }
    
      setRowLimit(rowLimit){
        this.setState({rowLimit})
      }
    
      renderLoading(){
        return <div>Loading ...</div>;
      }
    
      renderData(){
        return <div>
          {this.state.data.map(
             (item,key) => <DataItem item={item} key={key}/>
          )}
        </div>
      }
    
        render(){
            return (
          <div>
            <PageLink page={1} onClick={this.setCurrentPage}/>
            <RowSelector onChange={this.setRowLimit} selected={this.rowLimit}/>
            {this.state.loading ? this.renderLoading() : this.renderData()}
          </div>
        );
        }
    }
    
    ReactDOM.render(
      <Pagination />,
      document.getElementById('react')
    );
    

    你可以在这里看到这个工作:https://codepen.io/anon/pen/qPoBjN

    【讨论】:

    • 凯尔,你真的很棒。您的第一个直接固定代码很棒。它解决了上面列出的错误问题 2 和 3。但我仍然遇到这个错误 1 ​​问题。 “Uncaught TypeError: Cannot read property 'setState' of undefined”在渲染属性中。结果应该显示为 reactjs "dangerouslySetInnerHTML={{__html: this.state.data}}" 而不是 "$('#display').html(data).show();".. 对不起困惑。您可以从 Web 控制台查看错误。请这只是最后一个请求。感谢您及时的努力。我仍然指望你。
    • @bowman87 请查看更新的代码...另外,我强烈建议您重新编写代码,使其更像我的第二个示例。目前,您正在做一些非常奇怪的事情,这些事情没有意义并且违反标准。另外,我建议您阅读这篇文章:toddmotto.com/…
    • 你好凯尔,它没有显示任何东西。它仍然显示错误。 “未捕获的类型错误:无法读取未定义的属性‘setState’”在渲染属性中。
    猜你喜欢
    • 1970-01-01
    • 2014-06-25
    • 2019-12-13
    • 2018-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-20
    • 2018-04-26
    相关资源
    最近更新 更多