npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

react-simred

v2.0.0

Published

React bindings for Simred state manager

Downloads

13

Readme

react-simred NPM version Build Status Tests Coverage

React indings for Simred state management

If you're not sure what Simred is, visit the Simred project page for more information.

Table of Content


Installation

$ npm install --save react-simred

Usage

Hooks

Passing the store

import Simred from 'simred'
import { Provider } from 'react-simred'
import * as React from 'react'
import * as ReactDOM from 'react-dom'

import { App } from './components'
import { rootReducer } from './reducers'

const store = Simred.createStore(rootReducer)

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
)

useSelector(selector)

The useSelector() hook allows you to select the parts of the state you need.

import * as React from 'react'
import { useSelector } from 'react-simred'

export const UsernameComponent = (props) => {
  const user = useSelector(state => state.user)

  return <span>{user.firstname} {user.lastname}</span>
}

useActions(actionsSelector)

The useActions() hook allows you to get all or some of the actions in your store.

import * as React from 'react'
import { useSelector, useActions } from 'react-simred'

export const UsernameComponent = (props) => {
  const user = useSelector(state => state.user)
  const actions = useActions() // all actions in the store
  const userActions = useActions(actions => actions.user) // only userActions

  return <span>{user.firstname} {user.lastname}</span>
}

For Redux users

If you used React with Redux, it works the exact same way

Passing the store

import Simred from 'simred'
import { Provider } from 'react-simred'
import * as React from 'react'
import * as ReactDOM from 'react-dom'

import { App } from './components'
import { rootReducer } from './reducers'

const store = Simred.createStore(rootReducer)

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
)

Implementing Container Components

import * as React from 'react'
import { connect } from 'react-simred'
import { Component } from './components'

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

const mapActionsToProps = (actions) => {
  return { actions: actions.todos }
}

const Container = connect(mapStateToProps, mapActionsToProps)(Component)

export Container

For the rest of the world

To keep help understanding how this works, we'll keep following the todo list example from the Simred project page. Make sure you've read the complete to-do list example before continuing.

This tutorial is heavily inspired by this redux article

Presentational and Container Components

The bindings separate Presentational and Container Components. This helps separate presentation code from the business logic and makes components easier to reuse.

| | Presentational Components | Container Compoents | |---|---|---| |Purpose| How things look (markup, styles)| How things work (fetching data, state updates) | |Aware of Simred| No | Yes | |To read data| Reads data from props | Subscribes to Simred state | |To change data| Invokes callbacks from props | Calls Simred actions |

Designing components

The design is simple, we want to display a list of todos. On click, a todo is crossed as completed. We want a field to add a new todo, and a toggle to show all, only completed or remaining todos.

Presentational components
  • TodoList displays a list of todos props:
    • todos: Array list of todo items like {text, completed}
    • onTodoClick(id: number) callback called when a todo is clicked
  • TodoItem a single todo item: props:
    • text: string text to display
    • completed: boolean is whether or not the item has been crossed
    • onClick() callback call when a todo is clicked
  • Link a link with a callback props:
    • onClick() callback called when the link is clicked
  • Footer where the user changes the which todos to show
  • App root component rendering everything
Container compoenents
  • VisibleTodoList Filters todos according the current visiblity setting
  • FilterLink get the current visibilty filter and renders a link props:
    • filter: The visibility filter it represents
  • AddTodo Input field + "Add" button

Implementing components

From this spec it is not hard to implement these components

Presentationnal Components

components/TodoItem.js

import * as React from 'react'

export const Todo = ({ text, completed, onClick }) => {

  render (
    <li
    onClick={onClick}
    style={{
      textDecoration: completed ? 'line-through' : 'none'
    }}
  >
    {text}
  </li>
  )
}

components/TodoList.js

import * as React from 'react'
import { TodoItem } from './TodoItem'

export const TodoList = ({ todos, onTodoClick }) => (
  <ul>
    {todos.map((todo, index) => (
      <TodoItem key={index} {...todo} onClick={() => onTodoClick(index)} />
    ))}
  </ul>
)

components/Link.js

import * as React from 'react'

export const Link = ({ active, children, onClick }) => {
  if (active) {
    return <span>{children}</span>
  }

  return (
    <a
      href=""
      onClick={e => {
        e.preventDefault()
        onClick()
      }}
    >
      {children}
    </a>
  )
}

components/Footer.js

import * as React from 'react'
import { FilterLink } from './containers/FilterLink'
import { VisibilityFilters } from './filters'

export const Footer = () => (
  <p>
    Show: <FilterLink filter={VisibilityFilters.SHOW_ALL}>All</FilterLink>
    {', '}
    <FilterLink filter={VisibilityFilters.SHOW_REMAINING}>Remaining</FilterLink>
    {', '}
    <FilterLink filter={VisibilityFilters.SHOW_COMPLETED}>Completed</FilterLink>
  </p>
)
Container Components

Those are the components aware of the Simred state. react-simred provides a connect() function to hook up React components to the Simred state while preventing some unnecessary re-renders.

To use connect(), you need to define a special function called mapStateToProps that describes how to transform the current Redux store state into the props you want to pass to a presentational component you are wrapping. VisibleTodoList needs to calculate the todos to pass to TodoList in accordance with the visibilityFilter

import { VisibilityFilters } from './filter'

const getVisibleTodos = (todos, filter) => {
  switch (filter) {
    case VisibilityFilters.SHOW_COMPLETED:
      return todos.filter(t => t.completed)
    case VisibilityFilters.SHOW_ACTIVE:
      return todos.filter(t => !t.completed)
    case VisibilityFilters.SHOW_ALL:
    default:
      return todos
  }
}

const mapStateToProps = state => {
  return {
    todos: getVisibleTodos(state.todos, state.visibilityFilter)
  }
}

Container components can also call Simred actions. Same as mapStateToProps, you may define a mapActionsToProps that recieves all actions from the root reducer and returns the ones to pass to the container.

const mapActionsToProps = actions => {
  return {
    onTodoClick: actions.todos.toggle
  }
}

Finally, we create the VisibleTodoList by calling connect()

export const VisibleTodoList = connect(
  mapStateToProps,
  mapActionsToProps
)(TodoList)

And that is all there is to it.

Find the rest of the container components below: containers/FilterLink.js

import { connect } from 'react-simred'
import Link from '../components/Link'

const mapStateToProps = (state, ownProps) => {
  return {
    active: ownProps.filter === state.visibilityFilter
  }
}

const mapActionsToProps = (actions, ownProps) => {
  return {
    onClick: () => {
      actions.visibilityFilter.set(ownProps.filter))
    }
  }
}

export const FilterLink = connect(
  mapStateToProps,
  mapDispatchToProps
)(Link)

containers/AddTodo.js

import React from 'react'
import { connect } from 'react-redux'
import { addTodo } from '../actions'

let AddTodo = ({ addTodo }) => {
  let input

  return (
    <div>
      <form
        onSubmit={e => {
          e.preventDefault()
          if (!input.value.trim()) {
            return
          }
          addTodo(input.value)
          input.value = ''
        }}
      >
        <input
          ref={node => {
            input = node
          }}
        />
        <button type="submit">Add Todo</button>
      </form>
    </div>
  )
}

export const AddTodo = connect(
  () => {},
  actions => ({ addTodo: actions.todos.add })
)(AddTodo)

Wrapping all container in a single component

components/App.js

import * as React from 'react'
import { Footer } from './Footer'
import { AddTodo } from '../containers/AddTodo'
import { VisibleTodoList } from '../containers/VisibleTodoList'

const App = () => (
  <div>
    <AddTodo />
    <VisibleTodoList />
    <Footer />
  </div>
)

export App

Passing the store to the application

The containers need to be allowed access to the Simred state and actions. The <Provider> component from react-simred "magically" gives access to the store to all "connected" containers

index.js

import * as React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-simred'
import Simred from 'simred'
import { rootReducer } from './reducers'
import { App } from './components/App'

const store = Simred.createStore(rootReducer)

render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
)

And Voilà!

License

MIT © Gaël PHILIPPE