【问题标题】:Set initial state from props in React componenet从 React 组件中的 props 设置初始状态
【发布时间】:2019-12-03 15:00:00
【问题描述】:

我有这样一个组件,我在其中从 props 设置初始状态:

    class CarsModal extends PureComponent {
      constructor(props) {
        super(props);
        autoBind(this);

        const { data } = {} } = props;

        this.state = {
          selectedCar: data.category || '',
          cars: [],
          isSpam: data.spam,
          pick: data.pick,
          suitable: data.suitable,
          articles: false,
          show: false,
        };
        this.messageTimer = 0;
      }

      async componentDidMount() {
        const cars = await getCars();
        this.setState({
          cars,
        });
      }

      componentWillUnmount() {
        clearTimeout(this.messageTimer);
      }

      close() {

      }

      select(car) {
        this.setState({
          selectedCar: car,
        });
      }

      async save(scrapeRequest = false) {
        const { carId } = this.props;
        const {
          selectedCar,
          isSpam,
          pick,
          suitable,
          articles,
        } = this.state;

        await curateCar(storyId, {
          selectedCar,
          is_spam: isSpam,
          pick: pick,
          suitable: suitable,
          articles: articles,
          scrape: scrape,
        });

        if (!scrape) {
          this.setState({
            show: true,
          });
          clearTimeout(this.messageTimer);
          this.messageTimer = setTimeout(() => {
            this.setState({
              show: false,
            });
          }, 1500);
        }
      }

      scrape() {
        this.save(true);
      }

      toggle(key) {
        this.setState((state) => ({
          [key]: !state[key],
        }));
      }

      render() {
        const { show, curatorData } = this.props;
        const { author, cars, show } = this.state;

        return (
          <Modal
            show={show}
            onHide={this.handleClose}
            dialogClassName={cx('curate-modal')}
            centered
          >
            <ionClick={this.close} />
            <h3>Tools</h3>
            <div>
              <span>Auto:</span>
              <DropdownButton
                title={(
                  <>
                    {selectedAuthor}
                    <i />
                  </>
                )}

              >
                {cars.map((car) => (
                  <Dropdown.Item
                    key={author}
                    active={author === car}
                    onClick={() => this.select(author)}
                  >
                    {author}
                  </Dropdown.Item>
                ))}
              </DropdownButton>
            </div>
            {OPTIONS.map((option) => (
              <Option
                key={option.key}
                id={option.key}
                checked={this.state[option.key]}
                onChange={() => this.toggle(option.key)}
              >
                {option.content}
              </Option>
            ))}
            <div className={cx('update-info')}>
              <button
                type="button"
                onClick={() => this.save()}
              >
                Update
              </button>
              {showMessage && (
                <span>Updated</span>
              )}
            </div>
            <hr />
            <span
              className={cx('link')}
              onClick={this.scrape}
            >
              Scrape article
            </span>
            <a href='/'>Test 1</a>
            <a href='/'>Vtest 2</a>
          </Modal>
        );
      }
    }

    const mapDispatchToProps = (dispatch) => ({
      actions: bindActionCreators({ ...actions }, dispatch),
    });

    const mapStateToProps = (state) => ({
      userData: state.reducer.userData,
    });

但我知道从道具设置初始状态是反模式。我尝试使用getDerivedStateFromProps(nextProps, prevState) React component initialize state from props

但是在那之后我的状态每次都更新并且实际上并没有改变,它是否每次都使用相同的道具更新。我只需要在INITIAL 加载时设置初始状态。我该怎么做?

【问题讨论】:

标签: javascript reactjs


【解决方案1】:

我强烈建议您不要使用 getDerivedStateFromProps。这就是为什么 reactjs 博客有一篇文章叫做“你可能不需要派生状态”

我认为对于基于 props 设置初始状态到底有什么问题(以及 props 的意义)存在一些普遍的混淆。

props 的重点是它们提供了一种简单且一致的方式来传递数据,并且如果这些 props 发生变化,react 将在视图时自动更新。

状态的重点是提供一种一致的方式来在您的应用程序中存储“有状态”信息(也就是可以更改的信息)。

我们举几个例子:

(A) state (source of truth) =&gt; view // 这很好。真相的源泉是国家。

(B) state (source of truth) =&gt; props =&gt; view // 这很好。真相的来源是父组件的状态。 (或者,状态将是 redux 存储 - 也可以)

(C) redux store (source of truth) =&gt; props =&gt; state =&gt; view // 这很混乱。我们为什么不直接去store =&gt; props =&gt; view

(D) state (source of truth) =&gt; props =&gt; state =&gt; view // 这令人困惑。现在,我们将真相的来源分成了两个不同的国家。 但是,这不一定是所有情况下的反模式。

(E) state/store => props => state (after initial seed of data, this is the source of truth) => view

这不是一个反模式,所以只要你只使用上面的状态作为数据的初始种子。在随后的渲染中,(E)中的信息流实际上只是state =&gt; view。这是简单且单向的,具有单一的事实来源。

这个post 可能会有所帮助。

【讨论】:

    【解决方案2】:

    如何在 componentDidMount 中使用道具设置状态?

    componentDidMount(){
     this.setState({
      selectedCar: this.props.data.selectedCar
     })
    }
    

    【讨论】:

      猜你喜欢
      • 2023-03-08
      • 2015-05-10
      • 1970-01-01
      • 1970-01-01
      • 2020-11-02
      • 2020-04-04
      • 2021-06-04
      • 2019-09-02
      • 2019-12-23
      相关资源
      最近更新 更多