REACT:无法更新儿童道具

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了REACT:无法更新儿童道具相关的知识,希望对你有一定的参考价值。

我在更新头类时遇到麻烦,所以每当调用displaySection()时它都会更新它的className。我知道父状态发生了变化,因为在displaySection()中完成的控制台日志会记录this.state.headerVisible的变化但是我的子组件中的任何内容都没有变化,我不知道我错过了什么,我一直在尝试不同的几个小时的解决方案,我只是无法弄清楚我做错了什么,标题headerVisible值保持为TRUE而不是在状态改变时改变。

我在控制台中没有得到任何错误代码,只是来自子Header的prop headerVisible没有更新它的父状态更改。

谢谢!

class IndexPage extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      section: "",
      headerVisible: true,

    }
    this.displaySection = this.displaySection.bind(this)
  }

  displaySection(sectionSelected) {
    this.setState({ section: sectionSelected }, () => {
      this.sectionRef.current.changeSection(this.state.section)
    })

    setTimeout(() => {
      this.setState({
        headerVisible: !this.state.headerVisible,
      })
    }, 325)

    setTimeout(()=>{
      console.log('this.state', this.state)
    },500)
  }

  render() {

    return (
      <Layout>
            <Header selectSection={this.displaySection} headerVisible={this.state.headerVisible} />
      </Layout>
    )
  }
}
const Header = props => (
  <header className={props.headerVisible ? 'visible' : 'invisible'}>
       <div className="navbar-item column is-size-7-mobile is-size-5-tablet is-uppercase has-text-weight-semibold">
              <span onClick={() => { this.props.selectSection("projects")}}>
                {" "}
                Projects
              </span>
  </header>
)
答案

你的示例代码似乎有几个问题:

  1. 在标题中缺少结束div
  2. 在Header中的onclick中使用this.props而不是props

以下最小的例子似乎有效。我不得不删除你对this.sectionRef.current.changeSection(this.state.section)的调用,因为我不知道应该是什么sectionRef,因为它不在你的例子中。

class IndexPage extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      section: "",
      headerVisible: true,

    }
    this.displaySection = this.displaySection.bind(this)
  }

  displaySection(sectionSelected) {
    this.setState({ section: sectionSelected })

    setTimeout(() => {
      this.setState({
        headerVisible: !this.state.headerVisible,
      })
    }, 325)

    setTimeout(()=>{
      console.log('this.state', this.state)
    },500)
  }

  render() {

    return (
      <div>
            <Header selectSection={this.displaySection} headerVisible={this.state.headerVisible} />
      </div>
    )
  }
}

const Header = props => (
  <header className={props.headerVisible ? 'visible' : 'invisible'}>
       <div className="navbar-item column is-size-7-mobile is-size-5-tablet is-uppercase has-text-weight-semibold">
              <span onClick={() => { props.selectSection("projects")}}>
                {" "}
                Projects
              </span>
       </div>
  </header>
)

ReactDOM.render(
  <IndexPage />,
  document.getElementsByTagName('body')[0]
);
.visible {
  opacity: 1
}

.invisible {
  opacity: 0
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
另一答案

Header组件中的代码中存在标记错误 - div标记未关闭。此外,我想,你删除一些代码使示例变得容易,并且有this.sectionRef.current.changeSection(this.state.section)的工件因为没有定义this.sectionRef

正如@Felix Kling所说,当你根据以前的状态改变组件的状态时使用函数prevState => ({key: !prevState.key})

这里的任何方式都是您想要实现的目标的一个实例:

// @flow
import * as React from "react";
import Header from "./Header";

type
Properties = {};

type
State = {
    section: string,
    headerVisible: boolean,
};

class IndexPage extends React.Component<Properties, State> {

    static defaultProps = {};

    state = {};

    constructor(props) {
        super(props);
        this.state = {
            section: "",
            headerVisible: true,

        };
        this.displaySection = this.displaySection.bind(this)
    }

    displaySection(sectionSelected) {
        setTimeout(
            () => this.setState(
                prevState => ({
                    section: sectionSelected,
                    headerVisible: !prevState.headerVisible
                }),
                () => console.log("Debug log: \n", this.state)
            ),
            325
        );
    }

    render(): React.Node {
        const {section, headerVisible} = this.state;

        return (
            <React.Fragment>
                <Header selectSection={this.displaySection} headerVisible={headerVisible} />
                <br/>
                <div>{`IndexPage state: headerVisible - ${headerVisible} / section - ${section}`}</div>
            </React.Fragment>
        )
    }
}

export default IndexPage;

和标题组件

// @flow
import * as React from "react";

type Properties = {
    headerVisible: boolean,
    selectSection: (section: string) => void
};

const ComponentName = ({headerVisible, selectSection}: Properties): React.Node => {
    const headerRef = React.useRef(null);

    return (
        <React.Fragment>
            <header ref={headerRef} className={headerVisible ? 'visible' : 'invisible'}>
                <div className="navbar-item column is-size-7-mobile is-size-5-tablet is-uppercase has-text-weight-semibold">
                    <span onClick={() => selectSection("projects")}>Projects</span>
                </div>
            </header>
            <br/>
            <div>Header class name: {headerRef.current && headerRef.current.className}</div>
        </React.Fragment>
    );
};

export default ComponentName;

以上是关于REACT:无法更新儿童道具的主要内容,如果未能解决你的问题,请参考以下文章

如何将儿童类型传递给 HOC 反应的道具

Apollo:在订阅更新时更新 React 道具?

儿童片段到父母片段沟通

如何在 mapDispatchToProps 或更新道具后运行回调函数,使用 react redux?

在 React 中按下按钮时重新渲染道具数据

通过支撑2层儿童?