{"action":"created","issue":{"url":"https://api.github.com/repos/firebase/reactfire/issues/102","repository_url":"https://api.github.com/repos/firebase/reactfire","labels_url":"https://api.github.com/repos/firebase/reactfire/issues/102/labels{/name}","comments_url":"https://api.github.com/repos/firebase/reactfire/issues/102/comments","events_url":"https://api.github.com/repos/firebase/reactfire/issues/102/events","html_url":"https://github.com/firebase/reactfire/issues/102","id":159173445,"number":102,"title":"support the container component pattern","user":{"login":"bigblind","id":737493,"avatar_url":"https://avatars.githubusercontent.com/u/737493?v=3","gravatar_id":"","url":"https://api.github.com/users/bigblind","html_url":"https://github.com/bigblind","followers_url":"https://api.github.com/users/bigblind/followers","following_url":"https://api.github.com/users/bigblind/following{/other_user}","gists_url":"https://api.github.com/users/bigblind/gists{/gist_id}","starred_url":"https://api.github.com/users/bigblind/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bigblind/subscriptions","organizations_url":"https://api.github.com/users/bigblind/orgs","repos_url":"https://api.github.com/users/bigblind/repos","events_url":"https://api.github.com/users/bigblind/events{/privacy}","received_events_url":"https://api.github.com/users/bigblind/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":2,"created_at":"2016-06-08T14:11:21Z","updated_at":"2016-06-10T05:33:25Z","closed_at":null,"body":"A big part of the ReactJS community is moving from using mixins to using container components, and composing them together. I'd like to propose a `createFirebaseContainer` function (or possibly just `createContainer`, which would work as follows:\r\n\r\n```JavaScript\r\ncreateFirebaseContainer(component, refs);\r\n```\r\n# arguments\r\n\r\n  - **Component**:  The component you want to wrap\r\n  - **refs**: a `FirebaseRefs` (see below) object or function that returns such anobject\r\n\r\nIf `refs` is a function, it should take in the props that were passed to the container when rendered, and returns a `FirebaseRefs` object.\r\n\r\n# The `FirebaseRefs` object\r\n\r\nA `FirebaseRefs` object, is an object that looks like this:\r\n\r\n```JavaScript\r\n{\r\n  \"<propName>\": {\r\n    \"ref\": DatabaseRef,\r\n    \"type\": \"array\" | \"object\",\r\n  }\r\n  ...\r\n}\r\n```\r\n\r\nHere, `\"<propname>\"` is the name of a property you want to receive. \r\n`ref` should be the database reference you want to bind that property to.\r\n`type`should be either `\"array\"` or `\"object\"` depending on whether you want to bind to that reference as an array or an object.\r\n\r\n# Example Usage\r\n\r\nHere's an example for a `TodoList` component:\r\n\r\n```JavaScript\r\n\r\nconst TodoList = React.createClass({\r\n  render(){\r\n    return <ul>\r\n      {this.props.todos.map((todo) => {\r\n        return <li><input type=\"checkbox\" defaultChecked={todo.done}> {todo.text}</li>\r\n      })}\r\n    </ul>\r\n  }\r\n});\r\n\r\nexport default createFirebaseContainer(TodoList, {\r\n  todos:  {\r\n    ref: firebase.database().ref(\"/todos\"),\r\n    type: \"array\"\r\n  }\r\n});\r\n```\r\n\r\nNow, when you render the exported component, it would receive a `todos` prop, which represents the value in the database at `/todos`. When the value changes, the component is automatically re-rendered.\r\n\r\n# Using a function for `refs`\r\n\r\nYou may not know in advance where the data you need lives. For example, a TodoList will likely only want to show todos for a specific user. These items could live at `/todos/{userID}`. To make it easier to specify the refs at runtime, you can pass a function like this:\r\n\r\n```JavaScript\r\nconst TodoList = function(props) {\r\n  return <ul>\r\n    {props.todos.map((todo) => {\r\n      return <li><input type=\"checkbox\" defaultChecked={todo.done}> {todo.text}</li>\r\n    })}\r\n  </ul>\r\n};\r\n\r\nexport default createFirebaseContainer(TodoList, (props) => {\r\n  return {\r\n    todos:  {\r\n      ref: firebase.database().ref(\"/todos/\" + props.userID),\r\n      type: \"array\"\r\n    }\r\n  }\r\n});\r\n```\r\n\r\nNow, assuming we import the exported component as `TodoList`, we can render it as `<TodoList userID=\"123abc\" />`, and the todos for that user would be fetched.\r\n\r\n# Advantages\r\n\r\nThe big advantage for this approach, is that we support more types of components. We don't rely on the component having state,, so we can write functional components, as seen above. We don't rely on the component having mixins, so we can support ES6 classes.\r\n\r\nThis also aligns it more with other popular libraries in the React ecosystem, such as Relay's [`createContainer`](https://facebook.github.io/relay/docs/guides-containers.html), and react-redux's [`connect`](http://redux.js.org/docs/basics/UsageWithReact.html#container-components) (though it uses a somewhat diffeent way of calling the function).\r\n\r\nI'm willing to create a PR for this.\r\n"},"comment":{"url":"https://api.github.com/repos/firebase/reactfire/issues/comments/225097047","html_url":"https://github.com/firebase/reactfire/issues/102#issuecomment-225097047","issue_url":"https://api.github.com/repos/firebase/reactfire/issues/102","id":225097047,"user":{"login":"jwngr","id":4149793,"avatar_url":"https://avatars.githubusercontent.com/u/4149793?v=3","gravatar_id":"","url":"https://api.github.com/users/jwngr","html_url":"https://github.com/jwngr","followers_url":"https://api.github.com/users/jwngr/followers","following_url":"https://api.github.com/users/jwngr/following{/other_user}","gists_url":"https://api.github.com/users/jwngr/gists{/gist_id}","starred_url":"https://api.github.com/users/jwngr/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jwngr/subscriptions","organizations_url":"https://api.github.com/users/jwngr/orgs","repos_url":"https://api.github.com/users/jwngr/repos","events_url":"https://api.github.com/users/jwngr/events{/privacy}","received_events_url":"https://api.github.com/users/jwngr/received_events","type":"User","site_admin":false},"created_at":"2016-06-10T05:33:25Z","updated_at":"2016-06-10T05:33:25Z","body":"Thanks for copying this over to the other thread. I just responded on that thread, so let's keep the discussion there."}}
{"actor":{"display_login":"jwngr"}}