2016-03-02 2 views
3

Я создаю изоморфное приложение React. Рабочий процесс Сейчас я работаю через это:Реакция на вызов при каждом изменении

  1. Пользователь переходит на /questions маршрут, который делает на стороне сервера API вызова и загружает данные на этой странице. Это вызывает функцию renderData(), как она должна, и загружает все вопросы, которые пользователь видит.
  2. Пользователь нажимает кнопку добавления, чтобы добавить новый вопрос, и модальные всплывающие окна для ввода пользователем полей формы и создания нового вопроса.

С каждым изменением модальности функция 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; 

На щелчку

+0

Поскольку ваш метод renderData() 'вызывается в рендере, любое изменение состояния на' QuestionsPage' приведет к его срабатыванию. Ваше прослушивание вашего магазина, а затем в каждом магазине обновит ваш 'onChange', всегда будет срабатывать. Ваша кнопка вызывает его prop 'createQuestion', который затем вызывает ваш магазин' QuestionStore', который затем перезапускает цикл рендеринга. Вам нужна логика внутри вашего onChange, чтобы остановить 'setState', если он не нужен. – enjoylife

ответ

2

Это происходит потому, что каждое изменение заставляет вас вызвать метод setState и изменить состояние основной компонент. React вызовет функцию рендеринга для компонента каждый раз, когда он обнаружит изменение состояния.

  • Событие OnChange на ваши входы связаны с методами на главном компоненте
  • Каждый метод вызывает SetState
  • Это вызывает призыв оказать
  • Это вызывает вызов RenderData

React позволяет вам изменить это, переопределив функцию shouldComponentUpdate. По умолчанию эта функция всегда возвращает true, что вызовет вызов метода render. Вы можете изменить его так, чтобы только определенные изменения состояния вызывали перенаправление путем сравнения нового состояния со старым состоянием.

+0

Это работает спасибо. У вас есть идея, почему в функции 'createQuestion()' в основном компоненте она вызывает 'QuestionStore.createQuestion (this.state.question)', но в функции 'createQuestion()' параметр содержит все состояние ? – erichardson30

Смежные вопросы