反应:无法更新儿童道具

时间:2019-04-15 23:36:20

标签: javascript reactjs

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

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

谢谢!

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>
)

2 个答案:

答案 0 :(得分:1)

标头组件中的代码中存在标记错误-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;

答案 1 :(得分:1)

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

  1. 页眉中缺少结束div
  2. 在标题的跨度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>