user3277570
user3277570

Reputation:

React/Redux simple access to Store from Component

I'm trying to figure out how to user the reducers with and inside my React-Component. My goal is pretty easy - at least i thought so: I want to toggle a Drawer-Menu. I know I can solve this with React-Only, but I want to learn Redux.

So, I've got a Component…

import React, { Component } from 'react';

class Example extends Component {

// ???

  render() {
    return (
        <button className="burgerbutton" onClick={this.toggleDrawer}</button>
        <div className="drawerMenu isvisible" ></div>
    );
  }
}

export default Example;

also a Reducer

const initialState = {
  buttonstate: false
};

const example = (state = initialState, action) => {
  switch (action.type) {
    case 'TOGGLE_BTN':
      return Object.assign({}, state, {
        buttonstate: !state.buttonstate
      })
    default:
      return state
  }
}

export default example

and an Action (although I don't know where to put that since it's so simple)

export const toggleDrawer = () => {
  return {
    type: 'TOGGLE_DRAWER'
  }
}

I read a lot of tutorials and most of them want me to seperate between "Presentational Components" and "Container Components". I can't really see how these concepts apply here. So what do I have to do to do to make this work? Am I looking at this problem from the right angle or do I need 12 "Container Components" to solve this?


I really hope this question makes sense at all and/or is not a duplicate!

Upvotes: 0

Views: 396

Answers (2)

James Ganong
James Ganong

Reputation: 1171

First, I'm really enjoying using redux "ducks" which is basically a redux reducer bundle. You put your reducer, action constants, and action creators in one file (called a duck). Then you may have multiple ducks for different modules or pieces of state that you'd then combine with combineReducers.

While @duwalanise has the right idea, I'd rather see the second param of connect() be used to directly map the action to dispatch (and there's a good shortcut for it) instead of having to use this.props.dispatch

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { toggleDrawer } from './duck';

class Example extends Component {

  render() {
    const { buttonstate, togglerDrawer } = this.props;
    return (
      <div>
        <button className="burgerbutton" onClick={toggleDrawer}</button>
        <div className="drawerMenu isvisible" ></div>
      </div>
    );
  }
}

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

export default connect(mapStateToProps, { toggleDrawer })(Example);

One side note, if you have a handler method in your component, it's better to do .bind(this) inside the constructor instead of using an arrow function or .bind(this) inside the event, ie don't do this onClick={() => /* do something */ } or this onClick={this.myHandler.bind(this)} This is an interesting (and long) read on it.

To touch on the Container vs Presentational Component piece: The idea would be to put all of your logic, handlers, redux actions etc into your containers, and pass that through props to your simple (hopefully stateless/pure function) presentational components. Technically, your component the way it's written could be turned into a stateless component:

const Example = ({ buttonstate, togglerDrawer }) => (
  <div>
    <button className="burgerbutton" onClick={toggleDrawer}</button>
    <div className="drawerMenu isvisible" ></div>
  </div>
);

Upvotes: 0

duwalanise
duwalanise

Reputation: 1302

In redux you have to dispatch action to update reducer state. So normally a component is connected to the redux store and communication is done through dispatch.

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { toggleDrawer } from 'action file location';

class Example extends Component {

   toggleDrawerHandler() {
     this.props.dispatch(toggleDrawer())
   }


  render() {
    // access button state from this.props.buttonstate
    return (
        <button className="burgerbutton" onClick={this.toggleDrawerHandler.bind(this)}</button>
        <div className="drawerMenu isvisible" ></div>
    );
  }
}

export default connect((store) => {buttonstate: store.buttonstate})(Example);

Upvotes: 0

Related Questions