doctopus
doctopus

Reputation: 5647

Using redux connect with React hooks

This isn't a question about react-redux hooks like useSelector or useDispatch. I'm curious to know how old school react-redux connect() with a functional component and when it's necessary to use React hooks like useEffect in this example.

Suppose I have this functional component that renders a "Hello world" in green if someReduxData is present, otherwise it render it in red.

const RandomComponent = ({ someReduxData }) => {
  const style = {
    color: someReduxData ? "green" : "red";
  }; 

  return (
    <div style={style}>Hello world</div>
  );
}

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

export default connect(mapStateToProps)(RandomComponent);

Let's say when the component first mounts to the DOM, someReduxData is null. Then it changes state so it's not null anymore. Will this force a re-render of RandomComponent so it renders in green? If not, then I assume I will need to listen for changes on someReduxData with useEffect()?

Upvotes: 2

Views: 5917

Answers (1)

Zachary Haber
Zachary Haber

Reputation: 11017

It will force a re-render of RandomComponent. connect works the same regardless of class vs function component.

Here's an example using a function component: There's a setTimeout of 2 seconds before an action dispatches that turns the App div green.

There's also an example of that same component using a hook instead of connect.

The main difference between connect and hooks are that connect essentially acts as React.memo for the component. This can be toggled off with a boolean flag, but you likely will never have to do that: https://react-redux.js.org/api/connect#pure-boolean

const initialstate = {
  someReduxData: null,
};

const reducer = (state = initialstate, action) => {
  switch (action.type) {
    case 'action':
      return {
        someReduxData: action.data,
      };
    default:
      return initialstate;
  }
};

const actionCreator = (data) => {
  return {
    type: 'action',
    data,
  };
};

const store = Redux.createStore(reducer);

const App = ({ someReduxData }) => {
  return (
    <div className={someReduxData}>
      Some div -- Will turn green in 2 seconds
    </div>
  );
};

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

const WrappedApp = ReactRedux.connect(mapStateToProps)(App);

const AppWithHooks = () => {
  const someReduxData = ReactRedux.useSelector(state=>state.someReduxData);
  return (
    <div className={someReduxData}>
      Some div with a hook -- Will turn green in 2 seconds
    </div>
  );
};

ReactDOM.render(
  <ReactRedux.Provider store={store}>
    <WrappedApp />
    <AppWithHooks />
  </ReactRedux.Provider>,
  document.querySelector('#root')
);

setTimeout(() => store.dispatch(actionCreator('green')), 2000);
.green {
  background-color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js" integrity="sha256-7nQo8jg3+LLQfXy/aqP5D6XtqDQRODTO18xBdHhQow4=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.2.0/react-redux.min.js" integrity="sha256-JuJho1zqwIX4ytqII+qIgEoCrGDVSaM3+Ul7AtHv2zY=" crossorigin="anonymous"></script>

<div id="root" />

Upvotes: 2

Related Questions