在JSX中反应不重新加载函数

时间:2018-01-30 13:37:53

标签: reactjs react-redux jsx

我正在使用react-redux。

我有以下JSX(仅包含相关的片段):

  getQuestionElement(question) {
     if (question) {
       return <MultiChoice questionContent={this.props.question.question} buttonClicked={this.choiceClicked} />
     }
     else {
      return (
        <div className="center-loader">
          <Preloader size='big' />
        </div>
      )
    }
  }
  render() {
    return (
      <div>
        <Header />
        {
            this.getQuestionElement(this.props.question)
        }
      </div>
     ) 
  }
function mapStateToProps({ question }) {
  return { question };
}

export default connect(mapStateToProps, questionAction)(App);

当动作触发时,减速器更新问题支柱

this.props.question

我期待    {this.getQuestionElement(this.props.question)} 重新加载并提出新问题。

然而,这并没有发生。我不能以这种方式放置一个函数来重新加载它吗?

我的MultiChoice组件:

import React, { Component } from 'react';
import ReactHtmlParser from 'react-html-parser';
import './questions.css';

class MultiChoice extends Component {
    constructor(props) {
        super(props);
        this.state = {
            question: this.props.questionContent.question,
            answerArray : this.props.questionContent.answers,
            information: null
        }
        this.buttonClick = this.buttonClick.bind(this);
    }
    createButtons(answerArray) {
        var buttons = answerArray.map((element) => 
            <span key={element._id} onClick={() => { this.buttonClick(element._id) }} 
            className={"span-button-wrapper-25 " +  (element.active ? "active" : "")}>
                <label>
                    <span>{element.answer}</span>
                </label>
            </span>
        );
        return buttons;
    }
    buttonClick(id) {
        var informationElement;
        this.props.buttonClicked(id);
        var buttonArray = this.state.answerArray.map((element) => {
            if (element._id === id ){
                element.active = true;
                informationElement = element.information;
                return element;
            }
            else{
                element.active = false;
                return element;
            }
        });
        this.setState({
            answerArray: buttonArray,
            information: informationElement
        })
    }
    render() {
        return (
            <div className="question-container">
                <div className="question-view">
                    <div className="icon-row">
                        <i className="fa fa-code" />
                    </div>
                    <div className="title-row">
                        {this.state.question}
                    </div>
                    <div className="button-row">
                        {this.createButtons(this.state.answerArray)}
                    </div>
                    <div className="information-row">
                        {ReactHtmlParser(this.state.information)}
                    </div>
                </div>
            </div>
        );
    }
}

export default MultiChoice;

QuestionAction.js

import axios from "axios";
import { FETCH_QUESTION } from "./types"; 

export const fetchQuestion = (questionId, answerId) => async dispatch => {
    let question = null;
    if (questionId){
        question = await axios.get("/api/question/next?questionId=" + questionId + "&answerId=" + answerId);
    }
    else{
         question = await axios.get("/api/question/next");

    }
    console.log("question", question);
    dispatch({ type: FETCH_QUESTION, payload: question  }); 
  };

questionReducer.js

import {FETCH_QUESTION } from "../actions/types";

  export default function(state = null, action) {
    switch (action.type) {
      case FETCH_QUESTION:
        console.log("payload", action.payload.data);
        return { question: action.payload.data, selected: false };
      default:
        return state;
    }
  }

index.js(Combined Reducer)

import { combineReducers } from 'redux';
import questionReducer from './questionReducer';

export default combineReducers({
    question: questionReducer
});

和我的切入点: index.js

const store = createStore(reducers, {}, applyMiddleware(reduxThunk));

ReactDOM.render(
    <Provider store={store}>
        <App /> 
    </Provider>,
    document.getElementById('root')
);
registerServiceWorker();

请求console.log响应:

  render() {
    console.log("Stackoverflow:", this.props.question)
    .....

enter image description here

并在单击按钮(和reducer更新后,console.log更新,但

            this.getQuestionElement(this.props.question)

无法重新渲染

enter image description here

1 个答案:

答案 0 :(得分:0)

MultiChoice组件不应该将props存储在构造函数中的state中,这里有2个选项:

处理propsWillReceiveProps中的道具更改以更新状态

class MultiChoice extends Component {
    constructor(props) {
        super(props);
        this.state = {
            question: this.props.questionContent.question,
            answerArray : this.props.questionContent.answers,
            information: null
        }
        this.buttonClick = this.buttonClick.bind(this);
    }

    componentWillReceiveProps(nextProps) {
       this.setState({ 
         question: nextProps.questionContent.question,
         answerArray : nextProps.questionContent.answers,
         information: null
       });
    }

我们必须继续使用构造函数来设置初始状态,如docs:

  

React不会使用初始道具调用componentWillReceiveProps()   在安装过程中。

第二个选项:将其设为&#34;哑组件&#34;没有state 并且仅使用他的props来渲染某些内容(要在您的组件中做一些更深层的更改,尤其是处理&#34; active&#34;元素,它将必须由父组件处理。)