Description
Description
The learner app throws a TypeError when viewing locked units due to activeUnitId
being null, causing undefined property access errors in the sidebar component. This occurs when learners attempt to interact with units they don't have access to.
Environment
- Platform: OpenEdX
- Component: Learner App - Sidebar
- Tutor Version: Teak
Error Details
TypeError: Cannot read properties of undefined (reading 'unitIds')
Call Stack:
logEvent
src/courseware/course/sidebar/sidebars/course-outline/hooks.js:100:37
handleUnitClick
src/courseware/course/sidebar/sidebars/course-outline/hooks.js:112:5
onClick
src/courseware/course/sidebar/sidebars/course-outline/components/UnitLinkWrapper.tsx:49:20
handleClick
node_modules/react-router-dom/dist/index.js:560:18
HTMLUnknownElement.callCallback
node_modules/react-dom/cjs/react-dom.development.js:4164:14
Object.invokeGuardedCallbackDev
node_modules/react-dom/cjs/react-dom.development.js:4213:16
invokeGuardedCallback
node_modules/react-dom/cjs/react-dom.development.js:4277:31
invokeGuardedCallbackAndCatchFirstError
node_modules/react-dom/cjs/react-dom.development.js:4291:25
executeDispatch
node_modules/react-dom/cjs/react-dom.development.js:9041:3
processDispatchQueueItemsInOrder
node_modules/react-dom/cjs/react-dom.development.js:9073:7
processDispatchQueue
node_modules/react-dom/cjs/react-dom.development.js:9086:5
Root Cause
When a learner navigates to a locked unit, activeUnitId
becomes null. Subsequently, when clicking on any other unit, the following functions still attempt to execute with a null activeUnitId
:
sendTrackEvent
sendTrackingLogEvent
checkBlockCompletion
These functions expect a valid unitId but receive undefined/null, causing the TypeError when trying to access properties of the undefined value.
Steps to Reproduce
- Set up a course with unit prerequisites (locked units)
- Log in as a learner who hasn't completed the prerequisite
- Navigate to the course outline sidebar
- Navigate to a locked unit
- Attempt to click on another unit (any unit)
- Observe the TypeError in browser console
- Notice that tracking events and completion checks fail
Expected Behavior
- After viewing a locked unit, clicking on other units should work normally
- The app should gracefully handle null/undefined
activeUnitId
states - Sidebar navigation should remain functional even after interacting with locked content
- Tracking events should either be skipped or handled with default values when
activeUnitId
is null
Actual Behavior
- After viewing a locked unit,
activeUnitId
becomes null - Subsequent clicks on any unit throw TypeError when accessing properties of undefined
- JavaScript execution halts, breaking sidebar navigation functionality
- All tracking and completion checking fails until page refresh
Proposed Solution
Add defensive programming to the affected functions:
In handleUnitClick
function:
javascript
const handleUnitClick = (unitId) => {
if (!unitId || !activeUnitId) {
// Handle locked unit case gracefully
return;
}
// Existing logic...
};
In checkBlockCompletion
function:
javascript
const checkBlockCompletion = () => {
if (!activeUnitId) {
// Skip completion check for locked/undefined units
return;
}
// Existing logic...
};
Alternative Approach:
If tracking events need to run even for locked units, modify the functions to handle the locked state:
javascript
const sendTrackEvent = (unitId = null) => {
const trackingData = {
unitId: unitId || 'locked_unit',
// ... other properties
};
// Send tracking event with appropriate defaults
};
Impact
- Severity: Medium-High - Breaks sidebar navigation after viewing locked content
- Affected Users: Learners accessing courses with prerequisites
- Frequency: Occurs every time a learner navigates to a locked unit and then tries to access other units