poui
Version:
A React component for designating partial orders
180 lines (143 loc) • 7.39 kB
Markdown
In this stage we set-up the Node.js development environment with needed packages
and develop the list item component.
## Development environment
Both development and production require React, the UI component framework.
That in turn means we'll need Babel, and probably WebPack.
We need to install and manage a toolchain that extends the capabilities
of vanilla JavaScript in Node.js.
There are several options for initializing and managing this:
- Roll it ourselves by installing and configuring packages.
This can be quite maddening and can turn in to quite a time sink.
One resource for this is the Noteworthy post,
[Creating a React App... From Scratch](https://blog.usejournal.com/creating-a-react-app-from-scratch-f3c693b84658)
referenced from the React documentation.
- Use [create-react-app](https://github.com/facebook/create-react-app)
which leaves details of Babel and Webpack "preconfigured and hidden".
It requires tests to be mixed with the components under test in the
same directory.
- Use one of the "flexible toolchains" recommended in the React documentation
for [creating a React app](https://reactjs.org/docs/create-a-new-react-app.html#more-flexible-toolchains)
- One of these is
[nwb](https://github.com/insin/nwb/blob/master/docs/guides/ReactApps.md#developing-react-apps-with-nwb)
The `nwb` toolchain puts tests separate from the components.
### nwb
We tried `nwb`, but it hides details underneath its own shell, e.g.
```
"scripts": {
"build": "nwb build-react-component",
"clean": "nwb clean-module && nwb clean-demo",
...
},
```
Running `npm install` left ten audited vulerabilities
```
found 10 vulnerabilities (4 low, 5 moderate, 1 high)
```
Running `npm audit fix --force` produced:
```
10 vulnerabilities required manual review and could not be updated
```
meaning that some of these, one at minimum, need to be addressed, but we can't
address them without making changes to `nwb` itself,
because they're part of the dependencies of `nwb`.
Unfortunately, the roll-your-own route is the one that gets the job done.
### Installed packages
We follow the procedure from the Noteworthy post,
[Creating a React App… From Scratch](https://blog.usejournal.com/creating-a-react-app-from-scratch-f3c693b84658)
except, instead of using Webpack, we use Parcel.
We now have configured scripts in `package.json`:
- `npm run serve` which watches for and builds changes, runs a small web
server on `localhost:1234`
- `npm run watch` which watches for and builds changes
- `npm run build` which builds files into the `dist` directory
In the `package.json` file we have:
- Babel installed and configured with the
`preset-env` and `preset-react` presets.
- Parcel installed for build, with a lightweight web server for poking.
- React and ReactDOM
We have:
- a browser index file as `public/index.html` which loads the
application script and provides a target `div` in the page body for
React to render to.
- a top-level component, `App` from `src/App.js` that renders
an `h1` element.
- an index script as `src/index.js` that loads React and renders
the top level App component into the target `div` of the page.
The app runs. React renders the content of the App component.
## List item component
So, onward! We need a component that captures an item to be ranked.
We'll model it as a list item, although it will never be rendered without
JavaScript. It could just as well be a `<div>`, but `<li>` feels right.
If the partial order was rendered in plain old HTML it might look like this:
```
<ol>
<li>First ranked item</li>
<li><ul>
<li>One of two ranked second</li>
<li>Another of two ranked second</li>
</ul></li>
<li>Third ranked item</li>
<li>Fourth ranked item</li>
</ol>
```
### Tests
There are a few ways to organize tests:
- Place them in the component directory next to the components they are
testing. This mixes tests and code in the source. It places tests right
next to the code being tested.
- Place them in a `tests` directory that lives next to `src`, mirroring the
directory structure of `src`. This has certain advantages for packaging and
distribution-- simply ignore the `tests` directory. It results, however,
in a lot of directory traversal gymnastics in the imports.
- Place them in `tests` directories within the `src` directories, next to
the code being tested. This feels like a happy compromise between the first
two. It lends some structure and separation to the tests without imposing
a requirement to do directory gymnastics in the imports. The imports in
tests look like, for example, `import Item from '../Item';`.
We have to make a choice between Mocha and Chai vs. Jest. It could be a
toss-up. Jest looks simpler to set-up and use. Mocha has rich handling
for testing asynchronous code. In this case, we're developing a library
component. This isn't a full-fledged web application. It feels right to
keep testing simple and straightforward. Some might argue that both are
simple and straightforward. We're going with Jest here.
We have to make a choice between DOM testing library (DTL) and Enzyme.
One major difference is in the query methods. DTM focuses on what is visible.
Its queries focus on text, name, display value, etc. Enzyme allows queries
by internal, non-visible attributes such as classes, id's, and node types.
The philosophy of DTL is understandable, but we're going with Enzyme
in order to have access to all of the DOM attributes.
Installing Jest "added 181 packages from 109 contributors".
Installing Enzyme with the React-16 adapter
"added 33 packages from 22 contributors".
We build upon an almost instantly constructed, massive foundation of
openly distributed, mostly open source work from so many people and places.
### The component
Having the ability to test it, we construct `src/components/Item.js` with
a matching unit test in `src/components/tests/Item.test.js`.
More than just rendering an item, we want to be able to inject behaviors
to be triggered by click and drag. The behaviors will be both visible and
state changing.
To see that we'll be able to do that, we test that we can inject a function
called on click of the item.
#### class-properties
We like the
[class properties](https://babeljs.io/docs/en/babel-plugin-proposal-class-properties)
syntax for writing component classes.
Installing that creates a little bit of tech-debt. We'll have to adjust the
Babel plugins when this syntax moves to mainstream.
That isn't a huge increment above maintaining versions of things with
upgrades and patches.
### Styling
Having the component, we'd like it to look more like a clickable button
and not an HTML rendered list item with a bullet.
For now, we put the styling in the `App.css` file. We'll revisit this later
and most likely make a top-level stylesheet for the top-level component.
The component needs a class so that we can target the styling. We treat
styling for this component as a top-level block in the block-element-model
(BEM) paradigm.
We use font-relative units in order to maintain visual feel of the
component in the presense of larger or smaller font size settings.
To add some interactive, button-like behavior, we change the cursor shape
and alter the border color when the pointer tracks over the item.
## Next stage
[Etapa02](Etapa02.md) Implement container component.