React is a very useful component when creating web applications. This book is an excellent guide for you to learn this JavaScript library, whether you are a beginner or an expert.
Chapter 1- Handling of Complex States
Consider a situation in which you have some projects displayed on a table. let t = new Baobab({ projects: [{ id: 0, title: 'projectname' }, { id: 1, title: 'bar' }], selectedProject: null }); Consider the situation in which the user clicks on a project and then the data for the project is triggered: import Baobab from './t.js'; let actions = { selectProject(index) { t.set('selectedProject', t.get('projects')[index]); } }; export default actions; Note that the project has been referenced as the first project in the projects array. let t = new Baobab({ projects: [{ id: 0, title: 'projectname' }, { id: 1, title: 'bar' }], selectedProject: null }); Consider the situation in which the user clicks on a project and then the data for the project is triggered: import Baobab from './t.js'; let actions = { selectProject(index) { t.set('selectedProject', t.get('projects')[index]); } }; export default actions; Note that the project has been referenced as the first project in the projects array.
This is a problem which might get us into trouble. This is because any change made to an object or an array will change the reference on the Baobab. With the Baobab, one can easily determine whether an object has changed or not. A clone can be created so as to solve this problem. This is shown below: let Baobab = new Baobab ({ projects: [{ id: 0, title: 'projectname' }, { id: 1, title: 'bar' }], selectedProject: { id: 0, title: 'projectname' } }); At this point, we are having two instances of the same project. One is in the selectedProjects, and the other one in the projects.
This means that changing the selected project will not be reflected in the list of projects, and the vice versa is true. A pretty and complex logic has to be created so that everything runs well. Referencing in a List In our above project, we have selected only one project. It is possible that you have multiple projects and there is a need for them to be shown in a table. This will mean that multiple projects will be cloned as shown below: let t = new Baobab ({ projects: [{ id: 0, title: 'projectname' }, { id: 1, title: 'bar' }...1000], projectRows: [{ id: 0, title: 'projectrows' }, { id: 1, title: 'bar' }...10] }); We have a problem above just we had previously. Keeping in sync becomes a problem.
Reference within reference In relational databases, referencing of any object is done by use of an ID. Suppose our projects have comments. These have to be referenced by use of an ID. This is shown below: let t = new Baobab ({ comments: [{ id: 0, comment: 'commentname' }, { id: 1, comment: 'commentname' }], projects: [{ id: 0, title: 'projectname', comments: [0] }, { id: 1, title: 'bar', comments: [1] }...1000], projectRows: [{ id: 0, title: 'projectrows', comments: [{ id: 0, comment: 'commentname' }] }, { id: 1, title: 'bar', comments: [{ id: 1, comment: 'commentname' }] }...10] }); A more complex logic is needed at this point. This is because we do not need the ID of our comments, but we are in need of the comments themselves. This has to be handled during the time of cloning.
Baobab-react A context is now being used for the purpose of passing a state to the components. This is a much friendlier way how this can be done. The syntax itself is as follows: import Baobab from './Baobab.js'; import {root, branch} from 'Baobab-react/mixins'; /* Let us set up the top component first. The component will need our "root" mixin. The root mixin will expose the state Baobab on our context */ let Application = React.createClass({ mixins: [root], render() { return ( ); } }); /* Any of the child components in our application can attach the branch mixin. This mixin will allow you to attach cursors which will extract the state from our Baobab and attach it to our state object of our component */ let Hd = React.createClass({ mixins: , cursors: { foo: ['bar'] }, render() { return (
{this.state.name}
); } }); React.render(, document.getElementById('application')) Facets Components should have the ability to use cursors for composing a description of the User Interface (UI).
In this case, the facets should be used for composing the state. An example will best explain this as shown below: import Baobab from 'Baobab'; /* A Facet is simply an object having two special properties, that is, "cursors" and "get" */ let selectedProject = { cursors: { id: ['selectedProjectId'], projects: ['projects'] }, get: function (state) { return state.projects[state.id]; } }; /* We define our Baobab with some initial data and attach the facet */ let t = new Baobab({ projects: { '0': { title: 'projectname' }, '1': { title: 'bar' } }, selectedProjectId: '0' }, { facets: { selectedProject: selectedProject } }); export default Baobab; We have just begun by defining our facet which is an object having two properties. The example given below shows how a facet can be used: import React from 'react'; import {branch} from 'Baobab-react/mixins'; let P = React.createClass({ mixins: , facets: { p: 'selectedProject' }, render() { if (this.state.p) { return (
{this.state.p.title}
); } else { return null; } } }); export default P; As shown above, a property of facets can also be made to be available by use of the mixin. Its behavior will be similar to that of a cursor. It will grab the value which has been grabbed by our facet whenever the cursor has been updated. Suppose an action defined as follows is triggered by a component: import Baobab from './t.js'; let actions = { selectProject(projectId) { t.set('selectedProjectId', projectId); } }; export default actions; Our facet will first react, then the project component will be notified, and the new state will be grabbed from the facet.
Solution We need to display the projects list in a table. The approach to this can be as shown below: import Baobab from 't'; let projectsList = { cursors: { ids: ['projectsListIds'], projects: ['projects'] }, get: function (state) { return state.ids.map(function (id) { return state.projects[id]; }); } }; let t = new Baobab({ projects: { '0': { title: 'projectname' }, '1': { title: 'bar' } }, projectsListIds: [] }, { facets: { proList: proList } }); export default t; The component can use a facet similar to the one given below: import React from 'react'; import {branch} from 'Baobab-react/mixins'; let ProList = React.createClass({ mixins: , facets: { projects: 'proList' }, renderRow(p) { return ( ); }, render() { return (