简体   繁体   English

mapStateToProps 不更新具有切换状态的组件

[英]mapStateToProps not updating component with toggled state

new user to Redux so apologies for any silly mistakes. Redux 的新用户,对于任何愚蠢的错误深表歉意。 Ultimately, I am trying to toggle a className in component B as an onClick function toggles a state in component A.最终,我试图在组件 B 中切换一个类名,因为 onClick 函数在组件 A 中切换一个状态。

So it should be: Component A button click => state toggles => Component B className toggles.所以它应该是:组件 A 按钮单击 => 状态切换 => 组件 B className 切换。

I have setup my store and my mapDispatchToProps function that changes the state in my store seems to be working.我已经设置了我的商店,我的 mapDispatchToProps 函数改变了我商店的状态似乎正在工作。 However, calling this state in a different component is working... but, does not re-render as the state in the store toggles.但是,在不同的组件中调用此状态是有效的......但是,不会随着商店中的状态切换而重新呈现。 There is more content in my code, but I've tried to strip the parts that are not necessary to this issue.我的代码中有更多的内容,但我已经尝试删除了这个问题不需要的部分。

Component A - containing a button that toggles a state and changes a state within my store/rootReducer:组件 A - 包含一个按钮,用于切换状态并更改我的商店/rootReducer 中的状态:

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


function Nav(props) {
  const [showMenu, setShowMenu] = React.useState('menuClosed');

  function menuClick() {
    showMenu === 'menuClosed' ? setShowMenu('menuOpen') :
      setShowMenu('menuClosed');
  }

  // this works fine, I know this due to the console.log on my rootReducer page:
  React.useEffect(() => {
    props.toggleMenu(showMenu);
  }, [showMenu])


  return (
    <button className="hvr-icon-grow-rotate" id="bars" onClick={() => { menuClick(); }}>
      <FontAwesomeIcon icon={faBars} className="hvr-icon" />
    </button>
  )
}

const mapStateToProps = (state) => {
  return {
    menu: state.menu
  }
}

const mapDispatchToProps = (dispatch) => {
  return {
    toggleMenu: (showMenu) => {
      dispatch({ type: 'TOGGLE_MENU', menu: showMenu })
    }
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(Nav)

Component B: supposed to toggle a className depending on store state:组件 B:应该根据商店状态切换类名:

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

const [noHover, setNoHover] = React.useState('projectGrid');

  React.useEffect(() => {
    console.log('portfolio props: ' + props.menu + ' noHover: ' + noHover);
    if (props.menu === 'menuOpen') {
      setNoHover('projectGrid noHover');
      console.log('portfolio props: ' + props.menu + ' noHover: ' + noHover);
    }
    else if (props.menu === 'menuClosed') {
      setNoHover('projectGrid');
      console.log('portfolio props: ' + props.menu + ' noHover: ' + noHover);
    }
  }, [])

  return (<div className={noHover}>some content</div>);
}

const mapStateToProps = (state) => {
  return {
    menu: state.menu
  }
}

export default connect(mapStateToProps)(PortfolioItem)

finally, content of my rootReducer.js page, or the Redux store:最后,我的 rootReducer.js 页面或 Redux 商店的内容:

const initState = {
  menu: ['menuClosed']
}

const rootReducer = (state = initState, action) => {
  console.log(action);
  return state;
}

export default rootReducer;

Any help would be greatly appreciated - thank you!任何帮助将不胜感激 - 谢谢!

It doesn't look like you're actually toggling anything in your reducer.看起来您实际上并没有在减速器中切换任何东西。

You need to return a new state if you want it to change.如果你想让它改变,你需要返回一个新的状态。 I'm not sure exactly how it should look in your case, but something like this:我不确定在你的情况下它应该是什么样子,但是是这样的:

const rootReducer = (state = initState, action) => {
  let newState = {...state}; // Create a new state object so we don't mutate original
  switch(action.type) { // Check what type was sent to see if we should update
    case 'TOGGLE_MENU':
      newState.menu = action.menu; // Set new state based on action
      return newState;
    default:
      return state; // Return old state if nothing changed
  }
}

Side note: it looks like your initial state has menu as an array, but your components don't treat it as one.旁注:看起来您的初始状态将菜单作为数组,但您的组件不会将其视为一个数组。 It seems like it should be defaulted to a string.它似乎应该默认为一个字符串。

It looks like @brian-thompson has solved your problem, so I won't solve it again, but I would say you can make your styling logic a log easier by using the classnames library.看起来 @brian-thompson 已经解决了你的问题,所以我不会再解决它,但我会说你可以通过使用类名库使你的样式逻辑更容易成为日志。

Your useEffect callback would be replaced with您的 useEffect 回调将替换为

const { menu } = props
const noHover = classNames({
  'projectGrid': true,
  'noHover': menu === 'menuOpen'
})

Removing the need for any hooks.无需任何挂钩。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM