【问题标题】:React not reloading function in JSX在 JSX 中反应不重新加载功能
【发布时间】:2018-01-30 13:37:53
【问题描述】:

我正在使用 react-redux。

我有以下 JSX(仅包括相关的 sn-ps):

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

当动作触发时,reducer 更新问题道具

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(组合减速器)

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

点击按钮后(和reducer更新,console.log更新,但是

            this.getQuestionElement(this.props.question)

不会重新渲染

【问题讨论】:

  • 您可能正在修改您在questionAction 中发送的问题,您可以展示您的整个组件吗? (或调度动作的函数)
  • 我没有意识到这部分是相关的,我已经更新了问题
  • 是 QuestionReducer 唯一的 Reducer。请提及您是如何配置商店的,以及您对商店的减速器输入是什么样的
  • 当然,已更新。 (目前只有 1 个减速器)
  • 等一下。您在构造函数(MultiChoice 类)中使用 question 设置状态。也许您应该在 componentWillReceiveProps 中更新此状态或避免使用它?

标签: reactjs react-redux jsx


【解决方案1】:

MultiChoice 组件不应将他的props 存储在构造函数中的state 中,您有两个选择:

处理 componentWillReceiveProps 中的 props 变化以更新状态

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

我们必须继续使用构造函数来设置文档中的初始状态:

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

第二个选项:通过没有 state 并仅使用他的 props 来渲染某些内容(在您的组件中进行一些更深入的更改,尤其是处理“活动”元素,它必须由父组件处理)。

【讨论】:

  • 将其标记为答案,因为它解决了我的解决方案。我放弃使用“This.state”,仅使用 this.props 并将所有逻辑移至父级。
猜你喜欢
  • 1970-01-01
  • 2021-05-25
  • 2021-06-16
  • 2021-12-25
  • 2015-08-19
  • 2023-01-31
  • 2019-11-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多