【问题标题】:How to access state from closure in React如何在 React 中从闭包中访问状态
【发布时间】:2018-11-13 04:11:35
【问题描述】:

我的假设是我尝试从闭包中访问状态。 这在某种程度上不起作用:

当前代码:

export class CityChoice extends React.Component{
constructor(props) {
    super(props);
    this.state={}
}

componentDidMount(){
  request
    .get('http://XXX.XXX.XX.XX:3000/get_courses')
    .set('Accept', 'application/json')
    .then((res) => {
        for (let key in res.body){
          console.log(res.body[key].city)
        }
      this.setState({courses: res.body})
        console.log("this.state.courses -> " + this.state.courses)
    })
    .catch(function(err) {
      console.log(err)
    });
}

render(){
  var that = this
  return (<div>
            <h2>Wähle Deine Stadt</h2>
            {
            that.state.courses.body.city.map((city, index) => (
              <p><Link to={{pathname: "/kurse", stadt: {city}}}><Button>{city}</Button></Link></p>
            ))}
            }
          </div>
        )
    }
}

预期结果

x 按钮的输出命名并链接到各自的城市。

实际结果

TypeError: that.state.courses 未定义

【问题讨论】:

    标签: reactjs closures javascript-objects


    【解决方案1】:

    我对您的数据形式有些困惑。您遍历res.body,访问它的值并在这段代码中从每个值中打印出一个带有关键城市的值:

        for (let key in res.body){
          console.log(res.body[key].city)
        }
    

    然后您将res.body 分配给courses 中的this.state 键 这意味着状态形状有点像:

    this.state = {
      courses: [
             { city: "New York"},
             { city: "San Francisco"},
             { city: "Jerusalem"},
             { city: "Ho Chi Minh"}
            ]
    }
    

    courses 也可以是一个对象,但数组对我来说更有意义) 但是,当您访问状态时,您会编写以下表达式: that.state.courses.body.city.map。这意味着该状态看起来更接近:

    this.state = {
      courses: {
        body: {
          city: [
              "New York",
              "San Francisco",
              "Jerusalem",
              "Ho Chi Minh"
          ] 
        }
      }
    }
    

    现在因为这是 JavaScript,所以您可能在同一个对象中同时拥有两种状态形状。但坦率地说,这似乎不太可能,如果是这样,也是不明智的。我的建议是简化状态形状,以便可以将未定义的错误隔离到您状态中缺失的特定部分。如果一定是复杂的状态,写出格式。

    【讨论】:

      【解决方案2】:

      您的组件尝试在异步获取完成之前呈现 courses。因此,如果您无法按照@Tarik Sahni 的建议将课程初始化为适当的空状态,请使用条件渲染。

      {
          !this.state.courses
          ? ""
          : this.state.courses.body.city.map((city, index) => (
              <p><Link to={{pathname: "/kurse", stadt: {city}}}><Button>{city}</Button></Link></p>
          ))}
      }
      

      或者更简洁

      {
          this.state.courses && this.state.courses.body.city.map((city, index) => (
              <p><Link to={{pathname: "/kurse", stadt: {city}}}><Button>{city}</Button></Link></p>
          ))}
      }
      

      您无需在渲染函数中将this 分配给that

      【讨论】:

        【解决方案3】:

        课程正在从服务器获取,因此响应将在请求处理后出现。但是在初始渲染函数中没有称为courses 的状态属性。所以你可以在构造函数中将它们设置为空。

        constructor(props) {
         super(props);
         this.state={courses : {`what so ever is the data type`}}
        }
        

        在渲染时检查this.state.courses是否不为空。

        【讨论】:

        • 你的意思是渲染发生时数据可能还没有?
        猜你喜欢
        • 2020-11-28
        • 2020-11-05
        • 2015-03-08
        • 2016-11-14
        • 2020-10-07
        • 1970-01-01
        • 2018-09-25
        • 2017-12-05
        • 2014-11-21
        相关资源
        最近更新 更多