The React Blog Series: Part One This article is part one in a weekly series on building a blog with React and is the foundation to the rest of this series. The React Blog Series Building a website with React and Bulma ( ) Replacing Redux Thunks with Redux Sagas Part One: Building a Blog with React and Contentful Part Two: Import your Medium Feed into React Part Three: Adding a Redux to a React Blog Part Four: Part Five: In Progress Setup So lets install React npm install -g create-react-app aaronklaser cd aaronklaser npm start Next, lets install some of the stuff we know we will need: React HelmetBulmaBulma ExtensionsMomentStyled Components npm install bulma bulma-extensions moment react-helmet styled-components --save Setup React to use Sass This might not be completely necessary because we will mainly be using Styled Components, but this will make import Bulma much easier. Now for the tricky part, we need to setup Sass but I don’t want to have to eject from create-react-app. I followed this . tutorial npm install --save node-sass-chokidar This will create .css files of our .scss files, which I’m not super crazy about but for now lets roll with it. We will want to ignore our css files in git, so add src/**/*.css to our .gitignore file. Install npm-run-all so we can include our scss build in npm start npm install --save npm-run-all In the package.json in the npm scripts, add build-css and watch-css, build-js and watch-js, and modify build and start to use all our new scss stuff. "scripts": { "build-css": "node-sass-chokidar --include-path ./src --include-path ./node_modules src/ -o src/", "watch-css": "npm run build-css && node-sass-chokidar --include-path ./src --include-path ./node_modules src/ -o src/ --watch --recursive", "start-js": "react-scripts start", "start": "npm-run-all -p watch-css start-js", "build-js": "react-scripts build", "build": "npm-run-all build-css build-js", "test": "react-scripts test --env=jsdom", "eject": "react-scripts eject" } NOTE: It is important to include the --include-path ./src --include-path ./node-modules on both build-css and watch-css. This allows our code find libraries like Bulma in our node-modules folder. Adding Bulma and Bulma Extensions We are going to include Bulma and any Bulma config in the index component. Start by rename index.css to index.scss then restart your app using npm start If nothing blow up, and your project now includes index.scss index.css then it means everything is working correctly. and Next, in your index.scss import bulma. @import 'bulma/bulma'; @import 'bulma-extensions/extensions'; But, I’m going to do some additions steps to include an additional color because Bulma doesn’t include purple in its default colors and I kind of want purple. // 1. Import the initial variables @import "bulma/sass/utilities/initial-variables"; @import "bulma/sass/utilities/functions"; // 2. Setup your Custom Colors $purple: hsl(275,87%,45%); $purple-invert: findColorInvert($purple); // 3. Add new color variables to the color map. @import "bulma/sass/utilities/derived-variables.sass"; $addColors: ( "purple":($purple, $purple-invert), ); $colors: map-merge($colors, $addColors); @import 'bulma/bulma'; @import 'bulma-extensions/extensions'; Everything should start up and your fonts on your standard create-react-app home page should look different. Now, that we have all our setup done lets get some basic layout items in place using Bulma. Basic Layout and Header Let me take a quick minutes to talk about my file structure because its a little different then what you might be use to seeing. Fractal File Structure I first found the idea of . The idea wasn’t very clear the first time I read the article but one thing popped out at me and it think I understand it. I could be completely wrong, but never the less, my method has worked VERY well from me other the last few months. It a kind of extension to the ReDucks pattern, except you create a kind of key value or parent child object structure with your files. fractal file structures on an article on Hackernoon src |- index.js |- App.js |- app |- Layout.js |- layout |- Header.js |- Content.js |- Footer.js |- User.js |- user |- Profile.js |- PasswordReset.js |- Address.js |- components |- SharedCompOne.js |- SharedCompTwo.js So you can see we are starting to group our code by module or feature, but we don’t create a billion folders for each component. Instead, we are keeping our components in their parent folder, using for each component name, and for that components children folder. The only real exception here is App.js is technically a child of index, but I’m not sure that counts 🤔. PascalCasing camelCasing The benefit of this is that we can clearly see that Header, Content, and Footer are all components used in the Layout component which is used in the App component. If the filed structure was flatter like this: /* This is NOT fractal */ src |- index.js |- App.js |- layout |- Layout.js |- Header.js |- Content.js |- Footer.js Then we don’t have any real indication to the hierarchy of components or which components Layout.js is even used on, where as the fractal pattern shows you exactly who uses what components and where. Its a clear parent child structure, and layouts can even include a shared folder for components only shared within layout children. Remember how I mentioned key value structure earlier. This was the idea that made this all click in my head. So if you take my first example you think of it like this: src: { Index.js, App.js: { Layout.js: { Header.js Content.js Footer.js } } User.js: { Profile.js PasswordReset.js Address.js } components: { SharedCompOne.js SharedCompTwo.js } } Our site starts to look like JSON data… kinda, but you get the point. A “key” is always a component .js file. The “value” is as always folder with its key’s name and it contains all of the children components. Where this really starts to shine is in your store, which I keep separate from my presentation layer (app). We can now start structuring our store like our data structure. This works REALLY well with NoSQL. We will get more into this later. Lets start with the App In the root Create a folder named app and create file in it named Layout.js In the app folder, create folder named layout In the layout folder, create 4 files: Site.js, Header.js, Content.js, and Footer.js will call the Layout component and later include our Redux Store. App.js will contain and , which are just a wrapper for the site and content so we can get flexbox set up correctly, and and components. Layout.js Site.js Content.js Styled Component Header.js Footer.js Heres the set up of those 5 files places into a single Gist for both our convenience. <a href="https://medium.com/media/bdc0571966cd548f7757fd0bad898af4/href">https://medium.com/media/bdc0571966cd548f7757fd0bad898af4/href</a> Setup Routing to Some Pages npm install react-router-dom We are building a simple website/blog so we are going to use BrowserRouter. There are other option you can explore but this is not the thread for that ;) At the root of our application in the src/index.js we are going wrap the app with the router. import ReactDOM from 'react-dom' import registerServiceWorker from './registerServiceWorker' import { BrowserRouter as Router } from 'react-router-dom' import App from './App' import './index.css' ReactDOM.render(( <Router> <App /> </Router> ), document.getElementById('root')) registerServiceWorker() Then in the app folder, lets create two simple pages Home.js and Blog.js import React from 'react' const Home = () => ( <p>This is the Home Page</p> ) export default Home and import React from 'react' const Blog = () => ( <p>This is the Blog Page</p> ) export default Blog Now that we have some pages to route too, lets set up a Router component. For now, we are not going to try and do anything thing fancy with it, just the simple, straight forward Switch and Route. In our layout folder add a new file call Router.js . This router will live inside the on our Layout.js file. This wills house our basic top level pages. Content <Content> <Router /> </Content> Additional Routers components can be created in pages to add deeper nested routing. Our naming conventions for those in the future will be their parent component name and Router. Example, BlogRouter.js or HomeRoute.js. , they will live in a folder called blog. Remember In our router component, we need at the Switch component and inside it, a list or our routes using the Route component. import React from 'react' import { Switch, Route } from 'react-router-dom' import Home from './../Home' import Blog from './../Blog' const Router = () => ( <Switch> <Route exact path='/' component={Home}/> <Route path='/blog' component={Blog}/> </Switch> ) export default Router And Finally, lets go set up our Header to call these routes. For now, lets just make the changes for two pages we have routes for. We are going to modify our <a> on Blog and Logo Title nav items. <NavLink className="navbar-item" to="/" activeClassName="is-active" > <img style={{ borderTopLeftRadius: '50%', borderTopRightRadius: '50%', borderBottomLeftRadius: '50%', borderBottomRightRadius: '50%', marginRight: 15 }} src="https://media-exp2.licdn.com/mpr/mpr/shrinknp_400_400/AAEAAQAAAAAAAAU3AAAAJGE1MzYxNzYzLTE1NTUtNDEyYi04MzRjLTgzZjNkOGU0MGIzNg.jpg" width="30px" alt="" /> <span>AaronKlaser.com</span> </NavLink> and <NavLink className="navbar-item" to="/blog" activeClassName="is-active" > <span className="icon has-text-primary" style={{ marginRight: 5 }} <i className="fas fa-code"></i> </span> Code Blog </NavLink> Notice that we added activeClassName=”is-active” This is because that is the Bulma nav active class. The cool thing about NavLink is its always checking for what page your on, and if your route matches that NavLink to it will automagically add If you don’t want to add an active class, just simple us the Link component instead. is-active. Conclusion So this is the basic frame of the application. Review Set up a React site with create-react-app Set up React to build SassI Installed Bulma We learned about Fractal File Structures Created the site layout Set up Routing Added some pages to route to — Next Building a Blog with React and Contentful More to come! I will update this post accordingly.
Share Your Thoughts