Keep react component hover state in redux
Combine the reducer under the hover
state tree:
import { combineReducers } from 'redux';
import { reducer as hover } from '@bufferapp/redux-hover';
const app = combineReducers({
hover, // important to have this under the hover state tree
});
export default app;
Create a component that has a hovered
, onMouseEnter
and onMouseLeave
prop:
import React from 'react';
import { connectHoverable } from '@bufferapp/redux-hover';
const MyHoverableComponent = ({
hovered, // managed by redux-hover
onMouseEnter,
onMouseLeave,
}) => {
const style = {
background: hovered ? 'red' : 'blue',
};
return (
<div
style={style}
onClick={onClick}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
>
Hover This
</div>
);
};
MyHoverableComponent.propTypes = {
hoverId: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
]),
hovered: PropTypes.bool,
onMouseEnter: PropTypes.func,
onMouseLeave: PropTypes.func,
};
export default connectHoverable(MyHoverableComponent);
Place MyHoverableComponent
on the page and set a hoverId
:
import React from 'react';
import MyHoverableComponent from './MyHoverableComponent';
const App = () =>
<div>
<MyHoverableComponent hoverId={'myComponent'}/>
<MyHoverableComponent hoverId={'myOtherComponent'}/>
</div>;
export default App;
The hovered prop is set to true
on MyHoverableComponent
when the mouse is hovering over it. Otherwise it's set to false.
As long as id's are different, they'll be independently hoverable. The above example sets the strings manually, but you could also use a uuid()
too.
This also means that ids with the same value will all get the hover state applied when any of them are hovered.
React.clone
This keeps the number of elements on the page minimal but adds a little overhead to clone the hoverable component.
Sometimes there's cases where manually dispatching an action might be necessary. A good example is a button that removes itself (clearing a todo list item for example). The actions are exposed for this purpose so they can be dispatched:
import {
unhover,
} from '@bufferapp/redux-hover';
export const REMOVE_TODO = 'REMOVE_TODO';
export const removeTodo = todoListId => dispatch =>
Promise.all([
dispatch({
type: REMOVE_TODO,
todoListId,
}),
dispatch(unhover(`todo-list-item/remove-${todoListId}`)),
]);