Autoplay
Autocomplete
Previous Lesson
Complete and Continue
[LEGACY] React - The Complete Guide
Getting Started
Welcome To The Course! (0:44)
What is React.js? (2:58)
Join Our Online Learning Community
Why React Instead Of "Just JavaScript"? (10:57)
Editing Our First React App (4:24)
About This Course & Course Outline (2:19)
The Two Ways (Paths) Of Taking This Course (1:33)
Getting The Most Out Of This Course (3:04)
Creating React Projects: Browser-based vs Local Development (3:58)
Creating React Projects Locally (7:52)
Using CodeSandbox For React Development (No Local Setup Required!) (2:38)
The Academind Pro Referral Program
JavaScript Refresher
Module Introduction (1:49)
Starting Project (1:00)
Adding JavaScript To A Page & How React Projects Differ (6:57)
React Projects Use a Build Process (8:04)
"import" & "export" (12:04)
Revisiting Variables & Values (7:01)
Revisiting Operators (2:33)
Revisiting Functions & Parameters (8:14)
Arrow Functions (2:11)
Revisiting Objects & Classes (6:07)
Arrays & Array Methods like map() (11:10)
Destructuring (5:16)
The Spread Operator (3:13)
Revisiting Control Structures (5:28)
Manipulating the DOM - Not With React! (0:52)
Using Functions as Values (7:22)
Defining Functions Inside Of Functions (1:55)
Reference vs Primitive Values (4:45)
Next-Gen JavaScript - Summary
JS Array Functions
React Basics & Working With Components
Module Introduction (3:50)
What Are Components? And Why Is React All About Them? (7:26)
React Code Is Written In A "Declarative Way"! (3:49)
Creating a new React Project (2:08)
The Starting Project
Analyzing a Standard React Project (13:35)
Introducing JSX (4:03)
How React Works (4:34)
Building a First Custom Component (9:22)
Writing More Complex JSX Code (5:16)
Adding Basic CSS Styling (4:59)
Outputting Dynamic Data & Working with Expressions in JSX (8:41)
Passing Data via "props" (13:08)
Alternative Ways of Passing & Receiving / Handling "props" (5:09)
Adding "normal" JavaScript Logic to Components (6:12)
Splitting Components Into Multiple Components (11:28)
Time to Practice: React & Component Basics - Problem (2:31)
Time to Practice: React & Component Basics - Solution (7:25)
The Concept of "Composition" ("children props") (13:41)
A First Summary (4:16)
A Closer Look At JSX (9:31)
Organizing Component Files (3:09)
An Alternative Function Syntax (2:44)
Learning Check: React Basics, Components, Props & JSX
Module Resources
Time to Practice: Component Basics
Module Introduction (1:34)
The Starting Project & Your Tasks (4:48)
Exercise Hints
Outputting Key Concepts Data (5:51)
Identifying Possible Components (2:02)
Creating & Using a Custom Component (4:35)
Outsourcing Concept Items Into a Reusable Component (5:24)
Module Resources
React State & Working with Events
Module Introduction (2:33)
Listening to Events & Working with Event Handlers (10:05)
How Component Functions Are Executed (5:59)
Working with "State" (11:27)
A Closer Look at the "useState" Hook (7:59)
State can be updated in many ways!
Adding Form Inputs (10:24)
Listening to User Input (5:30)
Working with Multiple States (7:02)
Using One State Instead (And What's Better) (5:05)
Updating State That Depends On The Previous State (4:49)
Alternative: Creating A Shared Handler Function (6:17)
Handling Form Submission (5:07)
Adding Two-Way Binding (3:03)
Child-to-Parent Component Communication (Bottom-up) (14:35)
Lifting The State Up (7:19)
Time to Practice: Working with Events & State - Problem (2:32)
Time to Practice: Working with Events & State - Solution (8:42)
Derived / Computed State (6:54)
Controlled vs Uncontrolled Components & Stateless vs Stateful Components (5:39)
Learning Check: Working with Events & State
Module Resources
Rendering Lists & Conditional Content
Module Introduction (0:45)
Rendering Lists of Data (7:07)
Using Stateful Lists (4:30)
Understanding "Keys" (6:59)
Time to Practice: Working with Lists - Problem (1:15)
Time to Practice: Working with Lists - Solution (4:44)
Outputting Conditional Content (6:46)
Adding Conditional Return Statements (5:21)
Time to Practice: Conditional Content - Problem (1:01)
Time to Practice: Conditional Content - Solution (5:46)
Demo App: Adding a Chart (7:25)
Adding Dynamic Styles (7:28)
Wrap Up & Next Steps (11:04)
Learning Check: Outputting Lists & Conditional Content
Module Resources
Styling React Components
Module Introduction (3:43)
Setting Dynamic Inline Styles (8:58)
Setting CSS Classes Dynamically (5:00)
Introducing Styled Components (9:46)
Styled Components & Dynamic Props (8:30)
Styled Components & Media Queries (2:27)
Using CSS Modules (6:58)
Dynamic Styles with CSS Modules (5:31)
Module Resources
Debugging React Apps
Module Introduction (1:34)
Understanding React Error Messages (6:19)
Analyzing Code Flow & Warnings (5:53)
Working with Breakpoints (6:03)
Using the React DevTools (5:59)
Module Resources
Time to Practice: A Complete Practice Project
Module Introduction (2:36)
The First Practice Project & Your Tasks (6:28)
Exercise Hints
Splitting the App Into Components (7:24)
Handling Events (9:39)
Managing State (9:59)
Lifting the State Up (8:52)
Outputting Results Conditionally (10:06)
Adding CSS Modules (6:16)
Fixing a Small Bug
Introducing the Second Project (2:57)
Exercise Hints
Adding a "User" Component (7:06)
Adding a re-usable "Card" Component (8:37)
Adding a re-usable "Button" Component (3:50)
Managing the User Input State (4:57)
Adding Validation & Resetting Logic (4:34)
Adding a Users List Component (10:45)
Managing a List Of Users via State (9:27)
Adding The "ErrorModal" Component (8:04)
Managing the Error State (8:57)
Module Resources
Diving Deeper: Working with Fragments, Portals & "Refs"
Module Introduction (0:49)
JSX Limitations & Workarounds (8:46)
Creating a Wrapper Component (4:14)
React Fragments (2:42)
Introducing React Portals (4:20)
Working with Portals (12:24)
Working with "ref"s (11:47)
Controlled vs Uncontrolled Components (3:04)
Module Resources
Advanced: Handling Side Effects, Using Reducers & Using the Context API
Module Introduction (1:35)
What are "Side Effects" & Introducing useEffect (6:52)
Using the useEffect() Hook (10:57)
useEffect & Dependencies (9:01)
What to add & Not to add as Dependencies
Using the useEffect Cleanup Function (8:55)
useEffect Summary (3:38)
Introducing useReducer & Reducers In General (9:17)
Using the useReducer() Hook (14:12)
useReducer & useEffect (9:52)
useReducer vs useState for State Management (3:35)
Introducing React Context (Context API) (7:21)
Using the React Context API (10:44)
Tapping Into Context with the useContext Hook (1:42)
Making Context Dynamic (4:35)
Building & Using a Custom Context Provider Component (9:07)
React Context Limitations (2:45)
Learning the "Rules of Hooks" (7:10)
Refactoring an Input Component (6:06)
Diving into "Forward Refs" (13:39)
Module Resources
Practice Project: Building a Food Order App
Module Introduction (2:49)
Starting Setup (4:10)
Adding a "Header" Component (9:07)
Adding the "Cart" Button Component (5:26)
Adding a "Meals" Component (9:08)
Adding Individual Meal Items & Displaying Them (9:30)
Adding a Form (10:09)
Working on the "Shopping Cart" Component (5:10)
Adding a Modal via a React Portal (7:42)
Managing Cart & Modal State (10:48)
Adding a Cart Context (7:43)
Using the Context (4:52)
Adding a Cart Reducer (10:45)
Working with Refs & Forward Refs (10:49)
Outputting Cart Items (7:23)
Working on a More Complex Reducer Logic (5:29)
Making Items Removable (8:18)
Using the useEffect Hook (7:44)
Module Resources
A Look Behind The Scenes Of React & Optimization Techniques
Module Introduction (2:16)
How React Really Works (7:22)
Component Updates In Action (6:51)
A Closer Look At Child Component Re-Evaluation (10:41)
Preventing Unnecessary Re-Evaluations with React.memo() (11:36)
Preventing Function Re-Creation with useCallback() (4:13)
useCallback() and its Dependencies (7:10)
A First Summary (4:01)
A Closer Look At State & Components (3:30)
Understanding State Scheduling & Batching (9:05)
Optimizing with useMemo() (9:01)
Module Resources
An Alternative Way Of Building Components: Class-based Components
Module Introduction (2:10)
What & Why (4:52)
Adding a First Class-based Component (6:54)
Working with State & Events (11:38)
The Component Lifecycle (Class-based Components Only!) (5:20)
Lifecycle Methods In Action (11:46)
Class-based Components & Context (4:53)
Class-based vs Functional Components: A Summary (2:42)
Introducing Error Boundaries (9:52)
Module Resources
Sending Http Requests (e.g. Connecting to a Database)
Module Introduction (1:46)
How To (Not) Connect To A Database (3:32)
Our Starting App & Backend (3:52)
Sending a GET Request (10:35)
Using async / await (2:01)
Handling Loading & Data States (4:45)
Handling Http Errors (11:13)
Using useEffect() For Requests (6:27)
Preparing The Project For The Next Steps (6:16)
Sending a POST Request (9:16)
Wrap Up (1:16)
Module Resources
Building Custom React Hooks
Module Introduction (1:25)
What are "Custom Hooks"? (1:44)
Creating a Custom React Hook Function (6:39)
Using Custom Hooks (4:45)
Configuring Custom Hooks (5:51)
Onwards To A More Realistic Example (6:45)
Building a Custom Http Hook (9:16)
Using the Custom Http Hook (7:44)
Adjusting the Custom Hook Logic (8:45)
Using The Custom Hook In More Components (8:53)
Module Resources
Working with Forms & User Input
Module Introduction (1:36)
Our Starting Setup (1:41)
What's So Complex About Forms? (5:08)
Dealing With Form Submission & Getting User Input Values (10:04)
Adding Basic Validation (3:57)
Providing Validation Feedback (3:54)
Handling the "was touched" State (5:40)
React To Lost Focus (4:15)
Refactoring & Deriving States (9:07)
Managing The Overall Form Validity (7:30)
Time to Practice: Forms - Problem (1:22)
Time to Practice: Forms - Solution (5:45)
Adding A Custom Input Hook (12:44)
Re-Using The Custom Hook (2:54)
A Challenge For You! (1:41)
Applying Our Hook & Knowledge To A New Form (11:05)
Summary (3:17)
Bonus: Using useReducer() (8:22)
Module Resources
Practice Project: Adding Http & Forms To The Food Order App
Module Introduction (3:21)
Moving "Meals" Data To The Backend (4:05)
Fetching Meals via Http (9:27)
Handling the Loading State (4:00)
Handling Errors (7:44)
Adding A Checkout Form (10:47)
Reading Form Values (4:51)
Adding Form Validation (12:04)
Submitting & Sending Cart Data (6:48)
Adding Better User Feedback (9:28)
Summary (1:31)
Module Resources
Diving into Redux (An Alternative To The Context API)
Module Introduction (1:05)
Another Look At State In React Apps (5:14)
Redux vs React Context (6:19)
How Redux Works (5:48)
Important: createStore() is (Not) Deprecated
Exploring The Core Redux Concepts (15:14)
More Redux Basics (3:04)
Preparing a new Project (1:59)
Creating a Redux Store for React (4:54)
Providing the Store (3:13)
Using Redux Data in React Components (5:08)
Dispatching Actions From Inside Components (3:33)
Redux with Class-based Components (10:20)
Attaching Payloads to Actions (4:15)
Working with Multiple State Properties (6:19)
How To Work With Redux State Correctly (5:07)
Redux Challenges & Introducing Redux Toolkit (5:27)
Adding State Slices (8:11)
Connecting Redux Toolkit State (4:47)
Migrating Everything To Redux Toolkit (6:19)
Working with Multiple Slices (11:50)
Reading & Dispatching From A New Slice (6:56)
Splitting Our Code (5:03)
Summary (3:53)
Module Resources
Advanced Redux
Module Introduction (0:39)
Redux & Side Effects (and Asynchronous Code) (3:27)
Refresher / Practice: Part 1/2 (20:12)
Refresher / Practice: Part 2/2 (18:00)
Redux & Async Code (4:28)
Frontend Code vs Backend Code (5:40)
Where To Put Our Logic (8:59)
Using useEffect with Redux (6:00)
A Problem with useEffect()
Handling Http States & Feedback with Redux (12:49)
Using an Action Creator Thunk (12:07)
Getting Started with Fetching Data (8:39)
Finalizing the Fetching Logic (5:16)
Exploring the Redux DevTools (5:37)
Summary (1:52)
Module Resources
Building a Multi-Page SPA with React Router
Module Introduction (3:21)
Routing: Multiple Pages in Single-Page Applications (3:15)
Project Setup & Installing React Router (3:06)
Defining Routes (7:42)
Adding a Second Route (2:07)
Exploring an Alternative Way of Defining Routes (3:01)
Navigating between Pages with Links (4:36)
Layouts & Nested Routes (8:24)
Showing Error Pages with errorElement (3:58)
Working with Navigation Links (NavLink) (6:37)
Navigating Programmatically (2:41)
Defining & Using Dynamic Routes (7:44)
Adding Links for Dynamic Routes (3:22)
Understanding Relative & Absolute Paths (10:38)
Working with Index Routes (1:56)
Onwards to a new Project Setup (3:16)
Time to Practice: Problem (1:25)
Time to Practice: Solution (23:16)
Data Fetching with a loader() (7:35)
Using Data From A Loader In The Route Component (2:51)
More loader() Data Usage (3:17)
Where Should loader() Code Be Stored? (2:18)
When Are loader() Functions Executed? (2:48)
Reflecting The Current Navigation State in the UI (2:53)
Returning Responses in loader()s (4:01)
Which Kind Of Code Goes Into loader()s? (1:14)
Error Handling with Custom Errors (4:56)
Extracting Error Data & Throwing Responses (6:24)
The json() Utility Function (2:07)
Dynamic Routes & loader()s (7:32)
The useRouteLoaderData() Hook & Accessing Data From Other Routes (7:41)
Planning Data Submission (2:22)
Working with action() Functions (9:08)
Submitting Data Programmatically (9:06)
Updating the UI State Based on the Submission Status (4:02)
Validating User Input & Outputting Validation Errors (6:57)
Reusing Actions via Request Methods (7:55)
Behind-the-Scenes Work with useFetcher() (9:11)
Deferring Data Fetching with defer() (9:07)
Controlling Which Data Should Be Deferred (7:22)
Module Summary (2:57)
Adding Authentication To React Apps
Module Introduction (1:10)
How Authentication Works (9:08)
Project Setup & Route Setup (3:46)
Working with Query Parameters (7:35)
Implementing the Auth Action (11:40)
Validating User Input & Outputting Validation Errors (4:18)
Adding User Login (1:55)
Attaching Auth Tokens to Outgoing Requests (6:32)
Adding User Logout (4:21)
Updating the UI Based on Auth Status (6:05)
Adding Route Protection (2:46)
Adding Automatic Logout (5:10)
Managing the Token Expiratoin (7:28)
Deploying React Apps
Module Introduction (1:40)
Deployment Steps (3:35)
Understanding Lazy Loading (4:47)
Adding Lazy Loading (9:11)
Building the Code For Production (2:22)
Deployment Example (6:44)
Server-side Routing & Required Configuration (4:07)
React Query / Tanstack Query: Handling HTTP Requests With Ease
Module Introduction (1:46)
Project Setup & Overview (4:08)
React Query: What & Why? (5:59)
Installing & Using Tanstack Query - And Seeing Why It's Great! (16:32)
Understanding & Configuring Query Behaviors - Cache & Stale Data (7:43)
Dynamic Query Functions & Query Keys (13:05)
The Query Configuration Object & Aborting Requests (5:27)
Enabled & Disabled Queries (6:55)
Changing Data with Mutations (11:29)
Fetching More Data & Testing the Mutation (6:39)
Acting on Mutation Success & Invalidating Queries (8:50)
A Challenge! The Problem (2:14)
A Challenge! The Solution (16:37)
Disabling Automatic Refetching After Invalidations (2:42)
Enhancing the Demo App & Repeating Mutation Concepts (9:18)
React Query Advantages In Action (8:57)
Updating Data with Mutations (4:49)
Optimistic Updating (13:06)
Using the Query Key As Query Function Input (7:47)
React Query & React Router (20:26)
A (Pretty Deep Dive) Introduction to Next.js
Module Introduction (2:08)
What is NextJS? (4:45)
Key Feature 1: Built-in Server-side Rendering (Improved SEO!) (6:37)
Key Feature 2: Simplified Routing with File-based Routing (3:13)
Key Feature 3: Build Fullstack Apps (1:50)
Creating a New Next.js Project & App (5:39)
Analyzing the Created Project (2:52)
Adding First Pages (6:05)
Adding Nested Paths & Pages (Nested Routes) (3:47)
Creating Dynamic Pages (with Parameters) (3:36)
Extracting Dynamic Parameter Values (4:07)
Linking Between Pages (7:13)
Onwards to a bigger Project! (3:32)
Preparing the Project Pages (3:42)
Outputting a List of Meetups (5:03)
Adding the New Meetup Form (3:54)
The "_app.js" File & Layout Wrapper (6:17)
Using Programmatic (Imperative) Navigation (3:47)
Adding Custom Components & CSS Modules (10:00)
How Pre-rendering Works & Which Problem We Face (5:52)
Data Fetching for Static Pages (8:56)
More on Static Site Generation (SSG) (5:44)
Exploring Server-side Rendering (SSR) with "getServerSideProps" (6:27)
Working with Params for SSG Data Fetching (5:14)
Preparing Paths with "getStaticPaths" & Working With Fallback Pages (7:16)
Introducing API Routes (6:20)
Working with MongoDB (9:32)
Sending Http Requests To Our API Routes (6:49)
Getting Data From The Database (7:09)
Getting Meetup Details Data & Preparing Pages (9:41)
Adding "head" Metadata (9:19)
Deploying Next.js Projects (12:26)
Using Fallback Pages & Re-deploying (4:13)
Summary (2:15)
Module Resources
Animating React Apps with Framer Motion
Module Introduction (3:05)
Project Setup & Overview (1:42)
Animating with CSS Transitions (7:41)
Animating with CSS Animations (5:38)
Introducing Framer Motion (3:48)
Framer Motion Basics & Fundamentals (8:29)
Animating Between Conditional Values (4:13)
Adding Entry Animations (4:28)
Animating Element Disappearances / Removal (3:51)
Making Elements "Pop" With Hover Animations (4:13)
Reusing Animation States (3:28)
Nested Animations & Variants (7:46)
Animating Staggered Lists (4:29)
Animating Colors & Working with Keyframes (4:04)
Imperative Animations (7:28)
Animating Layout Changes (3:34)
Orchestrating Multi-Element Animations (10:05)
Combining Animations With Layout Animations (3:55)
Animating Shared Elements (4:15)
Re-triggering Animations via Keys (4:52)
Scroll-based Animations (15:44)
Animating React Apps
Module Introduction (2:58)
Preparing the Demo Project (4:56)
Using CSS Transitions (4:34)
Using CSS Animations (5:32)
CSS Transition & Animations Limitations (4:04)
Using ReactTransitionGroup (12:19)
Using the Transition Component (3:24)
Wrapping the Transition Component (3:16)
Animation Timings (3:14)
Transition Events (2:33)
The CSSTransition Component (5:23)
Customizing CSS Classnames (2:30)
Animating Lists (6:53)
Alternative Animation Packages (4:28)
Wrap Up (1:57)
Module Resources
Replacing Redux with React Hooks
Module Introduction (1:01)
Starting Project & Why You Would Replace Redux (4:19)
Alternative: Using the Context API (7:13)
Toggling Favorites with the Context API (5:43)
Context API Summary (and why NOT to use it instead of Redux) (2:30)
Getting Started with a Custom Hook as a Store (8:11)
Finishing the Store Hook (5:53)
Creating a Concrete Store (4:11)
Using the Custom Store (5:40)
Custom Hook Store Summary (3:13)
Optimizing the Custom Hook Store (4:04)
Wrap Up (2:00)
Bonus: Managing Multiple State Slices with the Custom Store Hook
Module Resources
Testing React Apps (Unit Tests)
Module Introduction (1:23)
What & Why? (3:23)
Understanding Different Kinds Of Tests (4:04)
What To Test & How To Test (1:29)
Understanding the Technical Setup & Involved Tools (2:39)
Running a First Test (7:16)
Writing Our First Test (10:14)
Grouping Tests Together With Test Suites (2:14)
Testing User Interaction & State (14:00)
Testing Connected Components (3:19)
Testing Asynchronous Code (9:11)
Working With Mocks (8:30)
Summary & Further Resources (3:47)
Module Resources
React & TypeScript
Module Introduction (1:26)
What & Why? (6:34)
Installing & Using TypeScript (6:38)
Exploring the Base Types (3:55)
Working with Array & Object Types (5:33)
Understanding Type Inference (2:47)
Using Union Types (2:48)
Understanding Type Aliases (2:42)
Functions & Function Types (5:19)
Diving Into Generics (8:01)
A Closer Look At Generics
Creating a React + TypeScript Project (8:34)
Working with Components & TypeScript (5:41)
Working with Props & TypeScript (14:20)
Adding a Data Model (9:09)
Time to Practice: Exercise Time! (7:02)
Form Submissions In TypeScript Projects (5:21)
Working with refs & useRef (10:56)
Working with "Function Props" (7:26)
Managing State & TypeScript (5:13)
Adding Styling (2:19)
Time to Practice: Removing a Todo (9:27)
The Context API & TypeScript (13:55)
Summary (2:18)
Bonus: Exploring tsconfig.json (5:46)
Module Resources
Optional: React Hooks Introduction & Summary
Module Introduction (2:10)
What Are React Hooks? (4:56)
The Starting Project (4:51)
Getting Started with useState() (9:20)
More on useState() & State Updating (11:54)
Array Destructuring (2:34)
Multiple States (3:47)
Rules of Hooks (2:20)
Passing State Data Across Components (7:56)
Time to Practice: Hooks Basics - Problem (1:03)
Time to Practice: Hooks Basics - Solution (2:55)
Sending Http Requests (7:16)
useEffect() & Loading Data (8:06)
Understanding useEffect() Dependencies (2:21)
More on useEffect() (9:37)
What's useCallback()? (5:28)
Working with Refs & useRef() (5:21)
Cleaning Up with useEffect() (3:20)
Deleting Ingredients (2:28)
Loading Errors & State Batching (8:48)
More on State Batching & State Updates
Understanding useReducer() (9:43)
Using useReducer() for the Http State (10:40)
Working with useContext() (8:27)
Performance Optimizations with useMemo() (10:30)
Getting Started with Custom Hooks (13:45)
Sharing Data Between Custom Hooks & Components (14:58)
Using the Custom Hook (8:11)
Wrap Up (3:05)
Module Resources
Optional: React Summary & Core Feature Walkthrough
Module Introduction (1:08)
What Is React & Why Would You Use It? (5:37)
React Projects - Requirements (2:09)
Creating React Projects (3:27)
Our Starting Project (3:28)
Understanding How React Works (7:46)
Building A First Custom Component (11:15)
Outputting Dynamic Values (5:03)
Reusing Components (6:00)
Passing Data to Components with Props (6:15)
CSS Styling & CSS Modules (10:07)
Exercise & Another Component (6:31)
Preparing the App For State Management (3:46)
Adding Event Listeners (7:52)
Working with State (10:00)
Lifting State Up (9:08)
The Special "children" Prop (7:21)
State & Conditional Content (8:59)
Adding a Shared Header & More State Management (7:51)
Adding Form Buttons (3:34)
Handling Form Submission (6:18)
Updating State Based On Previous State (5:30)
Outputting List Data (6:39)
Adding a Backend to the React SPA (6:10)
Sending a POST HTTP Request (4:12)
Handling Side Effects with useEffect() (9:06)
Handle Loading State (4:23)
Understanding & Adding Routing (3:55)
Adding Routes (5:36)
Working with Layout Routes (4:08)
Refactoring Route Components & More Nesting (5:35)
Linking & Navigating (8:09)
Data Fetching via loader()s (9:07)
Submitting Data with action()s (11:08)
Dynamic Routes (8:41)
Module Summary (1:25)
Course Roundup
What Now? Next Steps You Could Take! (3:19)
Explore The React Ecosystem! (4:27)
Finishing Thoughts (1:10)
Optional: Old Lectures
Using useReducer() for the Http State
Lesson content locked
If you're already enrolled,
you'll need to login
.
Enroll in Course to Unlock