【问题标题】:React: this.setState not resetting state反应:this.setState 不重置状态
【发布时间】:2018-10-19 00:35:43
【问题描述】:

我有一些数据要提炼来呈现,基本上我想要一个复选框来重置状态和 DOM,就像页面加载时一样。

最初,我在状态上有一个选定的属性,并有一个条件来确保它正在工作。那行得通。但我无法让它工作,我错过了什么?

2018 年 5 月 9 日更新

正如 Jay 下面建议的那样,我将把整个模块放在一个 sn-p 中,并专注于问题/问题的关键部分,

整个模块在一个sn-p下面...

我有一个显示对象数组的组件,每个对象都被提炼成自己的卡片。为了清楚起见,下面是一个屏幕截图。

这是我的组件中的方法:

handleReset() {
    this.setState({
      data: this.props.data,
    });
  }

这是正在渲染的 JSX。

<label>
  <input type="checkbox" onChange={this.handleReset} />
  <b>reset</b>
</label>

经过一段时间的思考,我意识到我的 handeReset 没有做任何事情可能是因为它只是呈现现在的状态。那么我的问题是如何回到 UI 最初的样子?预排序?

import React, {
  Component
} from 'react';
import {
  Card,
  Select,
  Segment,
  Container,
  Divider,
  Grid,
  Header,
  Image
} from 'semantic-ui-react';
import '../css/app.css';

class FilterOptions extends Component {
  constructor(props) {
    super(props);
    this.state = {
      data: this.props.data,
      priority: '',
      category: '',
      selected: false,
    };
    this.handleChange = this.handleChange.bind(this);
    this.handleReset = this.handleReset.bind(this);
  }

  handleReset() {
    this.setState({
      data: this.state.data,
    });
  }

  handleChange(e) {
    var val = e.target.value;
    if (!isNaN(val)) {
      this.setState({
        priority: val
      });
    } else if (isNaN(val)) {
      this.setState({
        category: val
      });
    }
    this.props.changeOption(val);
  }

  render() {
    var reset;
    if (!this.state.data) {
      reset = 'reset';
    } else {
      reset = 'not reset';
    }
    return ( <
      div >
      <
      h5 > By category < /h5> <
      label >
      <
      input type = "checkbox"
      onChange = {
        this.handleReset
      }
      />
      reset {
        reset
      } <
      /label> <
      h5 > By category < /h5> <
      ul >
      <
      li >
      <
      label >
      <
      input type = "radio"
      value = "cat1"
      checked = {
        this.state.category === 'cat1'
      }
      onChange = {
        this.handleChange
      }
      />
      cat1 <
      /label> <
      /li> <
      li >
      <
      label >
      <
      input type = "radio"
      value = "cat2"
      checked = {
        this.state.category === 'cat2'
      }
      onChange = {
        this.handleChange
      }
      />
      cat2 <
      /label> <
      /li> <
      li >
      <
      label >
      <
      input type = "radio"
      value = "cat3"
      checked = {
        this.state.category === 'cat3'
      }
      onChange = {
        this.handleChange
      }
      />
      cat3 <
      /label> <
      /li> <
      /ul> <
      h5 > By priority < /h5> <
      ul >
      <
      li >
      <
      label >
      <
      input type = "radio"
      value = "1"
      checked = {
        this.state.priority === '1'
      }
      onChange = {
        this.handleChange
      }
      />
      1 <
      /label> <
      /li> <
      li >
      <
      label >
      <
      input type = "radio"
      value = "2"
      checked = {
        this.state.priority === '2'
      }
      onChange = {
        this.handleChange
      }
      />
      2 <
      /label> <
      /li> <
      li >
      <
      label >
      <
      input type = "radio"
      value = "3"
      checked = {
        this.state.priority === '3'
      }
      onChange = {
        this.handleChange
      }
      />
      3 <
      /label> <
      /li> <
      li >
      <
      label >
      <
      input type = "radio"
      value = "4"
      checked = {
        this.state.priority === '4'
      }
      onChange = {
        this.handleChange
      }
      />
      4 <
      /label> <
      /li> <
      /ul> {
        /*<h5>By Color</h5>
                    <ul>
                      <li>
                        <label>
                          <input type="radio" value="Orange" checked={this.state.color === 'Orange'} onChange={this.handleChange} />
                          <div className="circle orange-filter-bg" />
                        </label>
                      </li>
                      <li>
                        <label>
                          <input type="radio" value="Green" checked={this.state.color === 'Green'} onChange={this.handleChange} />
                          <div className="circle green-filter-bg" />
                        </label>
                      </li>
                      <li>
                        <label>
                          <input type="radio" value="Blue" checked={this.state.color === 'Blue'} onChange={this.handleChange} />
                          <div className="circle blue-filter-bg" />
                        </label>
                      </li>
                      <li>
                        <label>
                          <input type="radio" value="Purple" checked={this.state.color === 'Purple'} onChange={this.handleChange} />
                          <div className="circle purple-filter-bg" />
                        </label>
                      </li>
                    </ul>*/
      } <
      /div>
    );
  }
}

function FilterUsers(props) {
  return ( <
    Container >
    <
    br / >
    <
    br / >
    <
    Grid columns = {
      3
    }
    doubling stackable > {
      props.data.map((user /* leveraging arrow functions implicit return */ ) => ( <
        Grid.Column key = {
          user.name
        } >
        <
        Segment className = {
          `priority${user.priority}`
        } >
        <
        Card >
        <
        Card.Content >
        <
        Card.Header >
        <
        h2 > name: {
          user.name
        } < /h2> <
        /Card.Header> <
        Card.Meta >
        <
        span className = "card__age" > age: {
          user.age
        } < /span> <
        /Card.Meta> <
        Card.Description > priority: {
          user.priority
        } < /Card.Description> <
        Card.Description className = "card__catergory" > category: {
          user.category
        } < /Card.Description> <
        /Card.Content> <
        /Card> <
        /Segment> <
        /Grid.Column>
      ))
    } <
    /Grid> <
    /Container>
  );
}

export default class SortAndFilterForm extends Component {
  constructor(props) {
    super(props);
    this.state = {
      data: this.props.data,
      priority: '',
      category: '',
    };
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(val) {
    if (!isNaN(val)) {
      this.setState({
        priority: val
      });
      var filteredByPriority = this.props.data.filter(function(item) {
        return parseInt(item.priority) === parseInt(val);
      });
    } else {
      this.setState({
        category: val
      });
      var filteredByPriority = this.props.data.filter(function(item) {
        return item.category === val;
      });
      this.setState({
        category: val
      });
    }

    console.log('filteredByPriority', filteredByPriority);
    this.setState({
      data: filteredByPriority
    });
  }
  render() {
    return ( <
      Container >
      <
      h1 > Sorts < /h1> <
      FilterOptions data = {
        this.state.data
      }
      changeOption = {
        this.handleChange
      }
      /> <
      FilterUsers data = {
        this.state.data
      }
      /> <
      /Container>
    );
  }
}

【问题讨论】:

  • 从上面大量注释掉的代码来看,我猜你只是在这里复制粘贴了你的整个模块。您可能会考虑剥离一些复杂性以专注于手头的问题。或者你可以建立一个最小的测试用例。这个过程通常会直接让我发现我做错了什么,但即使没有,我们也会更容易帮助你。
  • 你说的太对了!我想我认为这个问题对我来说似乎很容易理解,我应该意识到显然人们并不那么熟悉。任何人,我已经重构并更新了我的问题!谢谢@JayAllen!!!

标签: javascript reactjs


【解决方案1】:

我猜问题出在这里:

handleReset() {
  this.setState({
    data: this.state.data,
  });
}

您将state.data 设置为state.data 的位置,不出所料,这不会改变任何东西。我想你想做:

handleReset() {
  this.setState({
    data: this.props.data,
  });
}

【讨论】:

  • 谢谢朋友,但这并没有成功。我实际上认为,一旦你好心指出就是这样......
  • @AntonioPavicevac-Ortiz 尝试此解决方案后有什么变化吗?这也是我在查看您的代码时看到的问题。
【解决方案2】:

您的 HandleReset() 方法应该将所有内容设置为开始时的状态:

this.state = {
      data: this.props.data,
      priority: '',
      category: '',
    };

您的卡片使用 props.data.map 渲染,这意味着它们不会受到状态变化的影响。您应该使用来自状态的数据来呈现它们。

【讨论】:

  • 谢谢!这具有清除当前单选按钮选择的选择的效果,但不会重置 UI,即卡片
  • 用我认为导致卡片保持不变的原因更新了我的答案
  • 太好了,所以我的FilterUsers 组件是一个功能组件,这是否意味着我应该将它更改为一个类组件?因为现在获取数据的唯一途径就是通过 props。
  • 并非如此,您的 FilterUsers 组件应该只接受数据。不要让它接受道具/状态。这应该由使用该组件的代码来处理。
  • function FilterUsers(data) { return ( data.map((user /* 利用箭头函数隐式返回 */ ) =>
【解决方案3】:

如果我是你,我会把FilterOptions 变成一个纯粹的功能组件(例如只接受props,没有constructor,没有state,将handleResethandleChange 向上移动到@987654327 @ 并通过 props 将它们传递回去)。

SortAndFilterFormconstructor() 中,我会将其初始状态data 元素(已作为props.data 从其他东西传递给它)的副本 存储为状态变量(nb Object.assign 创建一个浅浅的副本,它似乎应该在这里工作,但它取决于内容以及您如何在其他地方对其进行变异):

this.state = {
  data: props.data,
  initData: Object.assign({}, props.data),
  priority: '',
  category: ''
}

SortAndFilterForm 中的 handleReset 方法如下所示:

handleReset() {
  this.setState({
    data: Object.assign({}, this.state.initData)
  })
}

你当然需要在SortAndFilterFormconstructor()中绑定它:

this.handleReset = this.handleReset.bind(this)

...并将其传递给FilterOptions:

    <FilterOptions
        data={this.state.data}
        changeOption={this.handleChange}
        resetOption={this.handleReset}   />

我相信以上所有内容都应该解决您的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-11-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-18
    • 2021-11-12
    • 2019-11-16
    • 1970-01-01
    相关资源
    最近更新 更多