每次更改都会调用React函数

时间:2016-03-02 17:41:41

标签: javascript reactjs

我正在构建一个同构的React应用程序。我目前正在处理的工作流程是:

  1. 用户导航到构成API调用服务器端的/questions路由,并在页面上加载数据。这会调用renderData()函数,并加载所有问题供用户查看。
  2. 用户点击添加按钮添加新问题,弹出模式以供用户输入表单字段并创建新问题。
  3. 随着模态的每次变化,renderData()函数被调用(它不应该被调用)。当用户单击Create Question按钮时,renderData()函数也会被调用,因为状态发生变化,因此会抛出错误。

    我无法确定每次在模态中发生任何事情时调用renderData()函数的原因。关于为什么会发生这种情况以及如何避免它的任何想法?

    主要组成部分:

    import React, { Component, PropTypes } from 'react';
    import withStyles from 'isomorphic-style-loader/lib/withStyles';
    import s from './QuestionsPage.scss';
    import QuestionStore from '../../stores/QuestionStore';
    import QuestionActions from '../../actions/QuestionActions';
    import Loader from 'react-loader';
    import QuestionItem from '../../components/QuestionsPage/QuestionItem';
    import FloatButton from '../../components/UI/FloatButton';
    import AddQuestionModal from '../../components/QuestionsPage/AddQuestionModal';
    
    const title = 'Questions';
    
    
    class QuestionsPage extends Component {
    
        constructor(props) {
            super(props);
            this.state = QuestionStore.getState();
            this.onChange = this.onChange.bind(this);
            this.openModal = this.openModal.bind(this);
            this.closeMOdal = this.closeModal.bind(this);
        }
    
      static contextTypes = {
        onSetTitle: PropTypes.func.isRequired,
      };
    
      componentWillMount() {
        this.context.onSetTitle(title);
        QuestionStore.listen(this.onChange);
    }
    
    componentWillUnmount() {
        QuestionStore.unlisten(this.onChange);
    }
    
    onChange(state) {
        this.setState(state);
    }
    
    openModal = () => {
        this.setState({ modalIsOpen: true});
    }
    
    closeModal = () => {
        this.setState({ modalIsOpen: false});
    }
    
    createQuestion = () => {
        const date = new Date();
        const q = this.state.question;
        q.createdAt = date;
        this.setState({ question : q });
        QuestionStore.createQuestion(this.state.question);
    }
    
    textChange = (val) => {
        const q = this.state.question;
        q.text = val;
        this.setState({ question : q });
    }
    
    answerChange = (val) => {
        const q = this.state.question;
        q.answer = val;
        this.setState({ question : q });
    }
    
    tagChange = (val) => {
        const q = this.state.question;
        q.tag = val;
        this.setState({ question : q });
    }
    
    companyChange = (val) => {
        const q = this.state.question;
        q.company = val;
        this.setState({ question : q });
    }
    
    renderData() {
        return this.state.data.map((data) => {
            return (
                <QuestionItem key={data.id} data={data} />
            )
        })
    }
    
      render() {
        return (
          <div className={s.root}>
            <div className={s.container}>
              <h1>{title}</h1>
                <div>
                    <Loader loaded={this.state.loaded} />
                    <FloatButton openModal={this.openModal}/>
                    <AddQuestionModal
                        open = {this.state.modalIsOpen}
                        close = {this.closeModal}
                        createQuestion = {this.createQuestion}
                        changeText = {this.textChange}
                        changeAnswer = {this.answerChange}
                        changeTag = {this.tagChange}
                        changeCompany = {this.companyChange}
                    />
                    { this.renderData() }
                </div>
            </div>
          </div>
        );
    }
    
    }
    
    export default withStyles(QuestionsPage, s);
    

    模态组件:

    import React, { Component, PropTypes } from 'react';
    import QuestionStore from '../../stores/QuestionStore';
    import QuestionActions from '../../actions/QuestionActions';
    import Modal from 'react-modal';
    import TextInput from '../UI/TextInput';
    import Button from '../UI/Button';
    
    class AddQuestionModal extends Component {
        createQuestion = () => {
            this.props.createQuestion();
        }
    
        closeModal = () => {
            this.props.close();
        }
    
        changeText = (val) => {
            this.props.changeText(val);
        }
    
        changeAnswer = (val) => {
            this.props.changeAnswer(val);
        }
    
        changeTag = (val) => {
            this.props.changeTag(val);
        }
    
        changeCompany = (val) => {
            this.props.changeCompany(val);
        }
    
        render() {
            return (
                <Modal
                    isOpen={this.props.open}
                    onRequestClose={this.closeModal} >
    
                    <TextInput
                        hintText="Question"
                        change={this.changeText} />
                    <TextInput
                        hintText="Answer"
                        change={this.changeAnswer} />
                    <TextInput
                        hintText="Tag"
                        change={this.changeTag} />
                    <TextInput
                        hintText="Company"
                        change={this.changeCompany} />
                    <Button label="Create Question" onSubmit={this.createQuestion} disabled={false}/>
                    <Button label="Cancel" onSubmit={this.closeModal} disabled={false}/>
                </Modal>
            );
        }
    }
    
    export default AddQuestionModal;
    

    点击

1 个答案:

答案 0 :(得分:2)

这种情况正在发生,因为每次更改都会导致您调用setState方法并更改主要组件的状态。每当检测到状态发生变化时,React都会调用组件的render函数。

  • 输入中的onChange事件绑定到主要组件上的方法
  • 每个方法都调用setState
  • 这会触发对渲染的调用
  • 这会触发对renderData的调用

React允许您通过覆盖shouldComponentUpdate函数来更改此值。默认情况下,此函数始终返回true,这将导致调用render方法。您可以对其进行更改,以便只有对状态的某些更改才会通过将新状态与旧状态进行比较来触发重定向。