简体   繁体   中英

How can I display/hide a component depending on a property on the Redux store?

I am studying Redux but I'm having problems to understand it properly. Now I am building a personal project with it to learn it.

I have this "Settings button" (actually, it is a list item) on the navbar. When I click it, I want that another component shows itself. This will be the <Settings /> component. This component has a "Close button" to hide.

My idea is to have a property on the redux global store like this: settingsOpen: false and when I click on the button it becomes true and the component appears and vice-versa. The close button always set the property equal to false and close the component.

Here you can find all the code: https://github.com/lbluigi/react-ecommerce

Anyway, I think the important parts are:

Header.js component

This is the list item clicked that would toggle the Settings component.

<a onClick={(event) => this.props.toggleSettings(event)} href="#settings" className="nav-link"><i className="fa fa-cog" aria-hidden="true"></i> Settings</a>

Settings.js component

This is the component that had to appear and disappear depending on the settingsOpens property.

<div className={this.props.settings.settingsOpen ? 'settings' : 'hidden'}>
  <i className="fa fa-times fa-3x" aria-hidden="true"></i>
  {/* just a test <h2>{this.props.settings.themeColor}</h2> */}
</div>

toggleSettings.js action This is the function triggered by the click event on the settings button that I wrote before.

event.preventDefault();
return {
  type: 'SETTINGS_TOGGLED'
}

settingsReducer.js reducer

This is the reducer that sets the initial properties that the user can change interacting with the Settings component.

{
  settingsOpen: false,
  themeColor: 'light',
  gridView: 'grid'
}

I could write a lot more, but you will find everything on the GitHub repo that I linked before. I don't know how to proceed to change the property settingsOpen on click.

Your settingsReducer must be a function which returns an object (state) by dispatching actions. In your case it should be:

const defaultSettings = {settingsOpen: false, themeColor: 'light'}
const settingsReducer = (state = defaultSettings, action) {
  if (action.type === 'SETTINGS_TOGGLED') {
    return {
      ...state,
      settingsOpen: !state.settingsOpen
    }
  }
  return state
}

I created a small example: https://codesandbox.io/s/wq24zkkrvw

Basically I initialised the store with a isOpen=false and every time you click on the button toggles the value of this.

reducer:

const initState = {
  isOpen: false
};
export default (state = initState, action) => {
  switch (action.type) {
    case 'TOGGLE':
      return { isOpen: !state.isOpen };
    default:
      return state;
  }
};

and this is the component that will dispatch the action:

<Counter
      isOpen={store.getState().isOpen}
      onToggle={() => store.dispatch({ type: 'TOGGLE' })}
    />

If you want to change some store property over time - you'll need a reducer. Because reducer is function that responsible for store mutations (changes). You already have one but it always return same value.

function settingsReducer() {
  return {
    settingsOpen: false,
    color: 'light',
    view: 'grid'
  }
}

Firstly you'll have to modify it in order to add reaction - once action appear, i would want to modify store like this: ,

function settingsReducer(state, action) {
    if (action.type === 'SETTINGS_TOGGLED') {
      return {
        settingsOpen: !state.settingsOpen,
        color: 'light',
        view: 'grid',
      };
    }
    return {
      settingsOpen: false,
      color: 'light',
      view: 'grid',
    };
  }

At that point you would have to create(define) an action .

After that proceed to a link in your header and add dispatch of an action instead returning value. Note that you have to connect header component for dispatching. Now your action will appear inside reducer and would be able to o modify store You can use some kind of a logger to check what is happening in your system After you make sure state is changing as you planned - you'd need to connect a Settings component to a store to pass settingsOpen property from store to component.

Thats where you return to you Settings component again, but from different side. Thinking in redux is always like this - you have to plan and implement whole loop. Somethink like: component handles click -> action -> reducer -> store changes -> component -> render changes

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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