- Create a React App in Your Local Environment
- Keeper App Project - Part 1 Challenge
2.1 Keeper App Project - Part 1 Challenge Final Code - Keeper App Project - Part 2 Challenge
3.1 Keeper App Project - Part 2 Challenge Final Code - Keeper App Project - Part 3 Challenge
4.1 Keeper App Project - Part 3 Challenge Final Code
4.1.1 Challenge Part 1 - Implement the add note functionality Code Completed
It sets up your development environment so that you can use the latest JavaScript features, provides a nice developer experience, and optimizes your app for production. You’ll need to have Node >= 10.16 and npm >= 5.6
on your machine. To create a project, run:
npx create-react-app my-app
cd my-app
npm start
Then open up the project folder and delete everything that is not needed, only leave: public/index.html
, src/index.js
, node_modules
, .gitignore
, package-lock.json
, package.json
, and README.md
.
⏳ 🧩 ❓ Below are the steps for part 1 challenge:
- Create a new React app.
- Create a App.jsx component.
- Create a Header.jsx component that renders a
<header>
element to show the Keeper App name in an<h1>
. - Create a Footer.jsx component that renders a
<footer>
element to show a copyright message in a<p>
with a dynamically updated year. - Create a Note.jsx component to show a
<div>
element with a<h1>
for a title and a<p>
for the content. - Make sure that the final website is styled like the example shown here
HINT: You will need to study the classes in the
styles.css
file to apply styling.
💻 ⚙️ ✔️ index.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Keeper App</title>
<link
href="https://fonts.googleapis.com/css?family=McLaren|Montserrat&display=swap"
rel="stylesheet"
/>
<link rel="stylesheet" href="styles.css"/>
</head>
<body>
<div id="root"></div>
<script src="../src/index.js" type="text/jsx"></script>
</body>
</html>
💻 ⚙️ ✔️ index.js
import React from "react";
import ReactDom from "react-dom";
//ES6 feature to import React components
import App from "./components/App.jsx";
ReactDom.render(
<App />,
document.getElementById("root")
);
💻 ⚙️ ✔️ App.jsx
/*
React needs to be imported as the code below is not actually JS
it is in fact JSX because we have the HTML elements which are
intermingling with actual JS code and we are only able to do this
because the React module actually converts the code below into real
JS using real JS functions such as document.createElement
*/
import React from "react";
//ES6 feature to import React components
import Header from "./Header.jsx";
import Footer from "./Footer.jsx";
import Note from "./Note.jsx";
function App(){
return (
<div>
<Header />
<Note />
<Footer />
</div>
);
}
/*
ES6 feature to export React components
we don't use parentheses (export default App();)
because it would make it return immediatelly, instead
we want to use it as a component (inside a HTML tag...)
*/
export default App;
💻 ⚙️ ✔️ Header.jsx
/*
React needs to be imported as the code below is not actually JS
it is in fact JSX because we have the HTML elements which are
intermingling with actual JS code and we are only able to do this
because the React module actually converts the code below into real
JS using real JS functions such as document.createElement
*/
import React from "react";
function Header(){
return <header>
<h1>Keeper</h1>
</header>
}
/*
ES6 feature to export React components
we don't use parentheses (export default Heading();)
because it would make it return immediatelly, instead
we want to use it as a component (inside a HTML tag...)
*/
export default Header;
💻 ⚙️ ✔️ Footer.jsx
/*
React needs to be imported as the code below is not actually JS
it is in fact JSX because we have the HTML elements which are
intermingling with actual JS code and we are only able to do this
because the React module actually converts the code below into real
JS using real JS functions such as document.createElement
*/
import React from "react";
function Footer(){
const currentYear = new Date().getFullYear();
return(
<footer>
<p>Copyright © {currentYear}</p>
</footer>
);
}
/*
ES6 feature to export React components
we don't use parentheses (export default Heading();)
because it would make it return immediatelly, instead
we want to use it as a component (inside a HTML tag...)
*/
export default Footer;
💻 ⚙️ ✔️ Note.jsx
/*
React needs to be imported as the code below is not actually JS
it is in fact JSX because we have the HTML elements which are
intermingling with actual JS code and we are only able to do this
because the React module actually converts the code below into real
JS using real JS functions such as document.createElement
*/
import React from "react";
function Note(){
return(
<div className="note">
<h1>Title</h1>
<p>Content</p>
</div>
);
}
/*
ES6 feature to export React components
we don't use parentheses (export default Heading();)
because it would make it return immediatelly, instead
we want to use it as a component (inside a HTML tag...)
*/
export default Note;
⏳ 🧩 ❓ Below are the steps for part 2 challenge:
- Render all the notes inside
notes.js
as a separateNote component
.
Now we have the notes.js files containing all the notes we need to render:
const notes = [
{
key: 1,
title: "Delegation",
content:
"Q. How many programmers does it take to change a light bulb? A. None – It’s a hardware problem"
},
{
key: 2,
title: "Loops",
content:
"How to keep a programmer in the shower forever. Show him the shampoo bottle instructions: Lather. Rinse. Repeat."
},
{
key: 3,
title: "Arrays",
content:
"Q. Why did the programmer quit his job? A. Because he didn't get arrays."
},
{
key: 4,
title: "Hardware vs. Software",
content:
"What's the difference between hardware and software? You can hit your hardware with a hammer, but you can only curse at your software."
}
];
💻 ⚙️ ✔️ App.jsx
/*
React needs to be imported as the code below is not actually JS
it is in fact JSX because we have the HTML elements which are
intermingling with actual JS code and we are only able to do this
because the React module actually converts the code below into real
JS using real JS functions such as document.createElement
*/
import React from "react";
//ES6 feature to import React components
import Header from "./Header.jsx";
import Footer from "./Footer.jsx";
import Note from "./Note.jsx";
import notes from "../notes.js";
console.log(notes);
function App() {
return (
<div>
<Header />
{notes.map((newNote) => (
//Return a Note component that has some props being sent over
<Note key={newNote.key} noteTitle={newNote.title} noteContent={newNote.content} />
))}
<Footer />
</div>
);
}
/*
ES6 feature to export React components
we don't use parentheses (export default App();)
because it would make it return immediately, instead
we want to use it as a component (inside a HTML tag...)
*/
export default App;
💻 ⚙️ ✔️ Note.jsx
/*
React needs to be imported as the code below is not actually JS
it is in fact JSX because we have the HTML elements which are
intermingling with actual JS code and we are only able to do this
because the React module actually converts the code below into real
JS using real JS functions such as document.createElement
*/
import React from "react";
function Note(props) {
return (
<div className="note">
<h1>{props.noteTitle}</h1>
<p>{props.noteContent}</p>
</div>
);
}
/*
ES6 feature to export React components
we don't use parentheses (export default Heading();)
because it would make it return immediately, instead
we want to use it as a component (inside a HTML tag...)
*/
export default Note;
⏳ 🧩 ❓ Below are the steps for part 3 challenge:
-
Implement the add note functionality. Create a constant that keeps track of the title and content. Pass the new note back to the App. Add new note to an array. Take array and render separate Note components for each item.
-
Implement the delete note functionality. Callback from the Note component to trigger a delete function. Use the filter function to filter out the item that needs deletion. Pass a id over to the Note component, pass it back to the App when deleting.
This is the end result you're aiming for.
index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./components/App";
ReactDOM.render(<App />, document.getElementById("root"));
CreateArea.jsx
import React from "react";
function CreateArea() {
return (
<div>
<form>
<input name="title" placeholder="Title" />
<textarea name="content" placeholder="Take a note..." rows="3" />
<button>Add</button>
</form>
</div>
);
}
export default CreateArea;
App.jsx
import React from "react";
import Header from "./Header";
import Footer from "./Footer";
import Note from "./Note";
import CreateArea from "./CreateArea";
function App() {
return (
<div>
<Header />
<CreateArea />
<Note key={1} title="Note title" content="Note content" />
<Footer />
</div>
);
}
export default App;
App.jsx
import React, {useState} from "react";
import Header from "./Header";
import Footer from "./Footer";
import Note from "./Note";
import CreateArea from "./CreateArea";
function App() {
/*
1. Implement the add note functionality.
In the app component - Add new note to an array.
The array will need state because it's going to be changed
the initial value for the notes will be an empty array
*/
const [notes, setNotes] = useState([]);
/*
1. Implement the add note functionality.
Pass the new note back to the App component
Trigger a function (addNote) that can pass the note back
over to the App.jsx we have to pass in a function
as a prop to do that, it will receive a note object
and will do something with the object
the addNote will be added as a value to one of the
props for the CreateArea (onAdd) and we will
set it equal to addNote
the value of newNote comes from CreateArea.jsx from the
function submitNote(event)...
*/
function addNote(newNote){
console.log(newNote);
/*
1. Implement the add note functionality.
In the app component - Add new note to an array.
add to the notes array
inside the setNotes function we can get hold of the
previous notes or whatever is the previous value of
the notes array
*/
setNotes(prevNotes => {
/*
Use the spread operator to add to the notes arrays so
that we get hold of all of the previous notes and then
add the new note at the end
the value of newNote comes from CreateArea.jsx from the
function submitNote(event)...
*/
return [...prevNotes, newNote];
});
}
return (
<div>
<Header />
<CreateArea
/*
1. Implement the add note functionality.
Pass the new note back to the App component
Trigger a function (addNote) that can pass the note back
over to the App.jsx we have to pass in a function
as a prop to do that, it will receive a note object
and will do something with the object
the addNote will be added as a value to one of the
props for the CreateArea (onAdd) and we will
set it equal to addNote
*/
onAdd={addNote}
/>
{/*
1. Implement the add note functionality.
Take array and render separate Note components for each item.
Use the notes array and map through it to render a different note
component for each item inside the array
the map will take an arrow function, and for each of the noteItem
inside the notes array, then return a new note component and
this note component will need some properties (title, content)
passed over
add curly braces around the code below for it to be recognized as JS code
*/}
{ notes.map((noteItem) => {
return <Note
title={noteItem.title}
content={noteItem.content}
/>
})}
<Footer />
</div>
);
}
export default App;
CreateArea.jsx
import React, {useState} from "react";
/*
1. Implement the add note functionality.
Pass the new note back to the App component
Now we'll trigger the addNote by getting hold
of the props that gets passed over and especially
the props.onAdd, and calling the onAdd from the props
is going to be equivalent to calling the addNote from App.jsx
and we need to pass it back as an input in order to be able to add the note
*/
function CreateArea(props) {
/*
1. Implement the add note functionality.
- Create a constant that keeps track of the title and content.
Save what's typed into the input under title and content
*/
//Create the state for the constants - create an object that contains title and content
const [note, setNote] = useState({
//The initial state will be an object with a title and content key set to an empty string each
title: "",
content: ""
});
/*
Receive an event when it gets triggered, and we'll destructure the event so
that we get hold of the event.target name and value so we create
a new destructured object using the const keyword and this destructured object
will tap into the event.target.name and event.target.value
*/
function handleChange(event){
const {name, value} = event.target;
/*
Now name and value can be used as separate constants and we can
add to the note by calling setNote. setNote will receive the previous note
and we will use that to add to the existing note, so we return a new object
with the previous note (prevNote) and in addition we will add the new
name and value
*/
setNote(prevNote => {
return {
...prevNote,
[name]: value
};
});
}
/*
1. Implement the add note functionality.
Pass the new note back to the App component
*/
function submitNote(event){
/*
event - Prevent the default behaviour (refresh page) of a button
inside a form when clicked by the user. The event is triggered by
the onClick and we can call event.preventDefault
*/
props.onAdd(note);
event.preventDefault();
}
return (
<div>
<form>
<input
/*
onChange - Now that we got the inputs controlled, the next step is to update them when
they get changed inside the onChange call a function (handleChange), and then we can
pass it in as the onChange
*/
name="title"
onChange={handleChange}
value={note.title}
placeholder="Title" />
<textarea
name="content"
onChange={handleChange}
value={note.content}
placeholder="Take a note..."
rows="5" />
{/*
1. Implement the add note functionality.
Pass the new note back to the App component
Get the note that's been created passed back to the App.jsx
When the button gets clicked we will pass a function (submitNote)
that should be triggered.
*/}
<button onClick={submitNote}>Add</button>
</form>
</div>
);
}
export default CreateArea;
This project was bootstrapped with Create React App
In the project directory, you can run:
Runs the app in the development mode.\ Open http://localhost:3000 to view it in the browser.
The page will reload if you make edits.\ You will also see any lint errors in the console.
Launches the test runner in the interactive watch mode.\ See the section about running tests for more information.
Builds the app for production to the build
folder.\
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.\ Your app is ready to be deployed!
See the section about deployment for more information.
Note: this is a one-way operation. Once you eject
, you can’t go back!
If you aren’t satisfied with the build tool and configuration choices, you can eject
at any time. This command will remove the single build dependency from your project.
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except eject
will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
You don’t have to ever use eject
. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
You can learn more in the Create React App documentation.
To learn React, check out the React documentation.
This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting
This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size
This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app
This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration
This section has moved here: https://facebook.github.io/create-react-app/docs/deployment
This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify