我必须为切换按钮使用useDispatch(),因此我必须使它们不反应到redux状态。我正在关注Redux的基础教程,并且我认为我已经正确地做到了,但是当我尝试至少使用Selector来显示按钮的redux'状态时,它什么都没有显示。

所以这是我的代码:

//操作文件夹中的types.js

   export const TOGGLE = "TOGGLE";


//动作文件夹中的buttonActions

 export const toggle = () => {
return {
type: 'TOGGLE'
};
};


// reducers文件夹中的buttonReducer

const buttonReducer = (state = true, action) => {
 switch(action.type) {
  case 'TOGGLE':
    return !state;
  default:
    return state;
};
};

 export default buttonReducer;


然后将buttonReducer导入到CombineReducers中进行存储。

组件代码:

import React, { useState, useEffect } from 'react'
import isloff from './mainpage_imgs/isloff.png'
import islon from './mainpage_imgs/islon.png'
import PropTypes from "prop-types";
import { connect, useDispatch, useSelector } from "react-redux";
import { toggle } from '../../actions/buttonActions'

  const Islbutton = props => {

const [open, setOpen] = useState(true);
const [role, setRole] = useState('');



useEffect(() => {
  if (props.auth.user)
  {
    setRole(props.auth.user.role);
  }
}, []);

const test = useSelector(state => state.button);

 const checkRole = (role) => {
  if (role === 'Menager' || role === 'Technolog')
   {
      return true }
    else
    {
      return false
    };
}

const toggleImage = () => {
if(checkRole(role)) {
setOpen(!open)
};
}

     const getImageName = () => open ? 'islOnn' : 'islOfff'

const dispatch = useDispatch();

            return(

              <div>

                <img style={islplace} src={open ? islon : isloff }
onClick={()=> dispatch(toggle())} />

              </div>
            );
    }


Islbutton.propTypes = {
button: PropTypes.func.isRequired,
auth: PropTypes.obj.isRequired
};

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

export default connect(mapStateToProps, {}), (Islbutton);

最佳答案

根据您的最新评论和对用例的理解,我建议采用以下简化方法:



//dependencies
const { render } = ReactDOM,
      { createStore } = Redux,
      { connect, Provider } = ReactRedux

//action creators
const SET_ROLE = 'SET_ROLE',
      MANAGER_APPROVED = 'MANAGER_APPROVED',
      setRole = role => ({type:SET_ROLE, role}),
      mngAppr = () => ({type:MANAGER_APPROVED})

//initial state, reducer, store
const initialState = {role:'Technolog', approved:false},
      appReducer = (state=initialState, action) => {
        switch(action.type){
          case SET_ROLE : {
            const {role} = state,
                  {role: newRole} = action
            return {...state, role: newRole}
          }
          case MANAGER_APPROVED : {
            const {approved} = state
            return {...state, approved: !approved}
          }
          default: return state
        }
      },
      store = createStore(appReducer)

//ui component to emulate toggling roles
const SwitchRoles = ({currentRole, switchRole}) => (
    <div>
      <label><input type="radio" name="role" value="Manager" onChange={e => switchRole(e.target.value)} />Manager</label>
      <label><input type="radio" name="role" value="Technolog"  onChange={e => switchRole(e.target.value)} />Technolog</label>
    </div>
)

//connect radio buttons click to togling roles action
const mapDispatch = dispatch => ({switchRole: role => dispatch(setRole(role))}),
      SwitchRolesContainer = connect(null,mapDispatch)(SwitchRoles)

//ui component to toggle 'approved' within global state
const ToggleApprove = ({onApprove,isManager}) => (
  <button onClick={onApprove} disabled={!isManager}>Toggle</button>
)

//connect onToggle handler to dispatching 'toggle' action
const mapStateToProps = ({role}) => ({isManager: role == 'Manager'}),
      mapDispatchToProps = dispatch => ({onApprove: () => dispatch(mngAppr())}),
      ToggleApproveContainer = connect(mapStateToProps, mapDispatchToProps)(ToggleApprove)

//ui component to display current state of 'open'
const IsApproved = ({isApproved}) => <div>{isApproved ? 'Approved by manager' : 'Not approved by manager'}</div>

//attach isOpen prop to global 'open' variable
const mapState = ({approved}) => ({isApproved: approved}),
      IsApprovedContainer = connect(mapState)(IsApproved)

//render the app
render (
  <Provider store={store}>
    <SwitchRolesContainer />
    <IsApprovedContainer />
    <ToggleApproveContainer />
  </Provider>,
  document.getElementById('root')
)

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.1.3/react-redux.min.js"></script><div id="root"></div>





希望它能为切换全局变量并将其值映射到局部组件状态提供一个思路。

关于javascript - 即使 Action 看起来正确, Action 也未定义或不可见,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59683229/

10-12 00:06
查看更多