【问题标题】:How to conditionally render an attribute of state如何有条件地呈现状态属性
【发布时间】:2019-10-28 08:56:58
【问题描述】:

我正在尝试获取一个下拉菜单来显示用户从上一页中选择的主题的名称(目前,它默认为“主题”)。

虽然我能够在控制台中获取 $r.state.topics[$r.state.topicSelected].name,但在我的代码中输入 this.state.topics[this.state.topicSelected].name 时出现未定义的错误。

所以,我尝试使用条件渲染将“主题”作为默认渲染,而主题本身是通过获取请求收集的。

<select
value={this.state.topicSelected}
onChange={this.onTopicClick}
className="sort"
data-element>
    {
    // Add this option in the .then() when populating siteCategories()
    [<option key={this.state.topicSelected}
      value={this.state.topicSelected}>({if 
       (this.state.topics[this.state.topicSelected].name == undefined) {
       'Topics'
    } else {
    this.state.topics[this.state.topicSelected].name
     }})
    </option>].concat(
this.state.topics.map(function (topic) {
 return (<option
 key={topic.id}
 value={topic.id}>{topic.name}</option>);
  }))
 }
</select>

我遇到了一个意外的令牌错误,但我尝试了各种语法组合但没有成功 - 如何正确运行这种条件格式?

【问题讨论】:

  • 这是什么,$r ?你是说this
  • 是的,$r 是您在 chrome 上的 react 开发工具中获得 this 的方式

标签: reactjs conditional-rendering


【解决方案1】:

您可以使用三元表达式? :。像这样,

this.state.topics[this.state.topicSelected] ? this.state.topics[this.state.topicSelected].name : 'Topics'

由于undefined 是一个假值,当this.state.topics[this.state.topicSelected] 未定义时,它将返回“主题”。

<select
  value={this.state.topicSelected}
  onChange={this.onTopicClick}
  className="sort"
  data-element>
      <option key={this.state.topicSelected}
        value={this.state.topicSelected}>
        {this.state.topics[this.state.topicSelected] ?
         this.state.topics[this.state.topicSelected].name : 'Topics'}
      </option>
      {this.state.topics.map(function (topic) {
         return (<option key={topic.id} value={topic.id}>{topic.name}</option>);
      })}
</select>

就你做事的方式而言,还有一些其他问题,但我认为它们与你的问题无关。一方面,您正在将列表的第一个选项更改为您选择的值。相反,您应该设置 select 的值,该值会自动从列表中选择正确的选项。我会这样写:

render() {
<select
  value={this.state.topicSelected}
  onChange={this.onTopicClick}
  className="sort"
  data-element>
      <option value={0}>Topics</option>
      {this.state.topics.map(topic => 
             <option key={topic.id} value={topic.id}>{topic.name}</option>))}
</select>
}

【讨论】:

  • 谢谢,但不幸的是我仍然收到Cannot read property 'name' of undefined
  • 哦,现在我明白了。让我重写它。
  • 我想我可能还需要对 keyvalue 应用相同的逻辑 - 当我选择一个主题时,它会覆盖“主题”,因此标题的名称会出现两次跨度>
  • 就您做事的方式而言,还有一些其他问题,但我认为它们与您的问题无关。一方面,您正在将列表的第一个选项更改为您选择的值。相反,您应该设置 select 的值,该值会自动从列表中选择正确的选项。
  • 好的,谢谢。这就是我最终想要实现的目标,另一个问题可能是 initialState 设置为 0 所以当用户返回一个页面时,它总是默认为 Topics
【解决方案2】:

您也可以将其设为受控组件,并默认状态如下

function App() {
  const [topics] = useState(["Math", "Geography"]);
  const [selectedTopic, setSelected] = useState("Topic");
  return (
    <select
      value={selectedTopic}
      onChange={(e) => setSelected(e.target.value)}
      className="sort"
    >
      <option>
        Topic
      </option>
      {topics.map(topic => (
        <option key={topic} value={topic}>
          {topic}
        </option>
      ))}
    </select>
  );
}

组件的类版本

class App extends React.Component {
  state = {
    topics: ["Math", "Geography"],
    selectedTopic: "Topic",
  }

  render() {
    const { selectedTopic, topics } = this.state;
    return (
      <select
      value={selectedTopic}
      onChange={(e) => this.setState({ selectedTopic: e.target.value })}
      className="sort"
      >
      <option>
        Topic
      </option>
      {topics.map(topic => (
        <option key={topic} value={topic}>
          {topic}
        </option>
      ))}
    </select>
    );
  }
}

此外,在您的渲染方法中,您不能有 if 语句,因为其中只允许使用 javascript 表达式。如果您需要使用条件语句,请使用三元运算符或使用 if 块创建一个函数,该函数可以从 render 中调用。你可以阅读更多关于表达式here

【讨论】:

  • 如果写成类组件会更好。 (因为他使用的是一个,所以钩子是完全不同的学习曲线)
猜你喜欢
  • 2023-04-07
  • 2021-02-28
  • 2015-05-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-30
  • 2011-10-19
  • 1970-01-01
相关资源
最近更新 更多