通过Redux更新商店后尝试重新渲染

时间:2018-08-29 06:53:00

标签: reactjs redux react-redux

我正在使用redux将菜单数据存储在存储区中。

它可以正常工作,但是一旦我通过分派更新存储,该组件就不会重新呈现,如果我使用this.forceUpadate,它可以工作,但我不想使用它。有什么解决办法吗?

代码

class MenuContents extends Component {
  constructor() {
    super();  
    this.state = {
      menu : []
    }    
  }
  componentDidMount() {
    // populate the left menu
    fetch("./services/left-menu.json")
    .then(res => res.json())
    .then(data => {
      store.dispatch( addLeftMenu(data))
      this.forceUpdate(); // I dont want to use this
    }).catch(function() {
      console.log("An error occured during fetch operation.");
    });
  }
  render() {
    let storeValue = store.getState();
    const leftMenu = storeValue.leftMenu[0];

    const isMenuLoaded = leftMenu !== undefined && leftMenu !== "";
    let menuContents;
    let menu;

    if(isMenuLoaded) {
        menuContents = leftMenu.map((menuItem, index)=> {

        menu = <li role="presentation" key={index}>
                  <a className="accordion-toggle" data-toggle="accordion" href="#">
                  {menuItem.name}
                  </a>

              </li>;
        return menu;
      }
      );
      menuContents = <ul className="nav nav-pills nav-stacked"> {menuContents} </ul>;
    }
    else {
      menuContents = <Spinner />
    }
    return (<div>{menuContents}</div>);
  }
}

export default MenuContents;

请参见下面的减速器代码。

reducer / index.js

import { ADD_LEFT_MENU } from "../constants/action-types";

const initialState = {
  leftMenu: []
};
const rootReducer = (state = initialState, action) => {
  switch (action.type) {
    case ADD_LEFT_MENU:
    return { ...state, leftMenu: [...state.leftMenu, action.payload]};
    default:
      return state;
  }
};
export default rootReducer;

3 个答案:

答案 0 :(得分:1)

如果您的访存调用不会导致更改道具或组件状态,React将无法知道您的组件需要重新渲染。您应该将组件与react-redux连接起来。直接访问组件中的redux存储不是通常的操作,因此不建议这样做。大多数生态系统都是围绕连接的组件构建的。

答案 1 :(得分:1)

我认为要摆脱Sakhi Mansoor所说的话,您想将组件连接到redux存储。我认为这是一篇很好的文章:

https://medium.com/mofed/reduxs-mysterious-connect-function-526efe1122e4

当组件的状态或道具更改时,基本上会重新渲染组件。现在,您有一个组件,并且有一个商店。需要发生的是,您将触发一些操作,该操作将使减速器消耗一些东西。 reducer将更新redux存储。然后,理想情况下,商店将更新组件的道具,然后触发重新渲染。

我认为您所缺少的是最后一部分。当您像文章中一样调用connect时,它将把商店连接到组件。因此,只要商店的某些部分发生变化,它就会更新组件中的相关道具。

答案 2 :(得分:1)

import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';

class MenuContents extends Component {
  constructor() {
    super();  
    this.state = {
      menu : []
    }    
  }
  componentDidMount() {
    // populate the left menu
    fetch("./services/left-menu.json")
    .then(res => res.json())
    .then(data => {
      store.dispatch( addLeftMenu(data))
    }).catch(function() {
      console.log("An error occured during fetch operation.");
    });
  }
  render() {
    let storeValue = store.getState();
    const leftMenu = storeValue.leftMenu[0];

    const isMenuLoaded = leftMenu !== undefined && leftMenu !== "";
    let menuContents;
    let menu;

    if(isMenuLoaded) {
        menuContents = leftMenu.map((menuItem, index)=> {

        menu = <li role="presentation" key={index}>
                  <a className="accordion-toggle" data-toggle="accordion" href="#">
                  {menuItem.name}
                  </a>

              </li>;
        return menu;
      }
      );
      menuContents = <ul className="nav nav-pills nav-stacked"> {menuContents} </ul>;
    }
    else {
      menuContents = <Spinner />
    }
    return (<div>{menuContents}</div>);
  }
}

const mapStateToProps = state => ({
   leftMenu: state.leftMenu,
});

const mapDispatchToProps = dispatch => ({
   addLeftMenu: bindActionCreators(addLeftMenu, dispatch),
});


export default connect(mapStateToProps, mapDispatchToProps)(MenuContents);