These ten questions run the length of the chapter, and each turns on a behavior that is easy to get wrong: what the runtime reports, how styles merge, how dp become pixels, what a schema returns, when a store notifies, how locales format, what MMKV 18,748 reads back, where links go, what localhost means on an emulator, and how Hermes 11,328 sorts. Every block ran on the Android 16 emulator inside this chapter's finished BookNest, as the demo screen src/demos/Quiz.tsx (opened at booknest:///demo), in a debug build on Expo SDK 57 6,418 with React Native 0.86.3 36,878 and Hermes, with the practice API of Query and Zustand running and an empty cart. The blocks ran in order, each as the body of its own function, and printed to the Metro terminal. Treat each numbered block as separate. Write down what it prints and why, then check Appendix H, which gives the real output, the reason and the section it comes from.
To run them yourself, start the practice API with node server.mjs and Metro with npx expo start, make src/demos/Current.tsx re-export the quiz screen, and open the demo route with adb shell am start -a android.intent.action.VIEW -d "booknest:///demo" (Deep Links). A debug build that shows the red "Unable to load script" screen is looking for Metro on the wrong port: adb reverse the port it expects, or set the bundler address in the developer menu (Opening React Native DevTools). Question 3 assumes the emulator's 420 dpi screen, and question 9 assumes that nothing forwards the emulator's own port 8150; on a physical phone both answers change. Question 5 empties the persisted cart, so run it on a test install. The app logs other lines in between, such as the routes Expo Router 6,418 visits and the tab bar's renders; the answers show only what each block prints.
Questions
// 1. What does the runtime report? (Sections 3.1.5 and 3.9.6)
const pick = Platform.select({ native: 'native', default: 'default', android: 'android' });
console.log(typeof g.HermesInternal, g.RN$Bridgeless, Platform.Version, pick);
// 2. What does flatten return, and how many pixels is a hairline? (Section 3.2.8)
const s = StyleSheet.flatten([{ padding: 4, color: 'red' }, false,
[{ color: 'blue' }, null, { padding: undefined }]]);
console.log(JSON.stringify(s), 'padding' in s, StyleSheet.hairlineWidth * PixelRatio.get());
// 3. How many physical pixels are these sizes on the 420 dpi emulator? (Section 3.9.5)
const px = [0.1, 0.5, 1, 8.4].map((dp) => PixelRatio.getPixelSizeForLayoutSize(dp));
console.log(px.join(' '), PixelRatio.roundToNearestPixel(0.1));Questions 4 and 5 call BookNest's own code, so reread checkoutSchema (Schema Validation with Zod) and the cart store with its remove action (Zustand Slices) before answering; question 6 uses the plural-rules polyfill that src/i18n/index.ts loads (Dates, Numbers and RTL).
// 4. Which checkouts pass, and what data comes back? (Section 3.18.3)
const form = { name: ' Al ', email: 'al@example.com', address: ' 12 Jalan Gaya ' };
for (const [delivery, postcode] of [['pickup', 'x'], ['ship', '88000 '], ['ship', '8800']]) {
const r = checkoutSchema.safeParse({ ...form, delivery, postcode });
console.log(delivery, r.success ? JSON.stringify(r.data)
: JSON.stringify(z.flattenError(r.error).fieldErrors));
}
// 5. How often does the listener run, and what is left in the cart? (Section 3.17.3)
useCart.getState().clear();
let calls = 0;
const unsubscribe = useCart.subscribe(() => calls++);
const { add, remove } = useCart.getState();
add(3); add(3); remove(5); remove(3);
unsubscribe();
console.log(calls, selectCount(useCart.getState()), JSON.stringify(useCart.getState().items));
// 6. Plural forms, and a price compared with a string you typed (Sections 3.25.4, 3.26.7)
const ar = new Intl.PluralRules('ar');
console.log(i18n.t('cart.items', { lng: 'en', count: 0 }), '|',
[0, 1, 2, 3, 11, 100].map((n) => ar.select(n)).join(' '));
const es = new Intl.NumberFormat('es', { style: 'currency', currency: 'USD' }).format(24);
console.log(es === '24,00 US$', es.length, es.charCodeAt(5));Question 8 calls the link rewrite of Deep Links directly, with initial: false, so each call also logs its incoming link: line; the answers leave those lines out.
// 7. A number stored in MMKV, read back three ways (Section 3.20.3)
const kv = createMMKV({ id: 'quiz' });
kv.set('n', 3);
console.log(JSON.stringify([kv.getString('n'), kv.getNumber('n'), kv.getBoolean('n')]),
kv.contains('n'));
kv.clearAll();
// 8. Where does each old-style link go? (Section 3.16.6)
for (const path of ['booknest://item?id=4', 'booknest://olditem?id=7&x=1',
'booknest://book/item?id=9', 'booknest://Item?id=2']) {
console.log('->', redirectSystemPath({ path, initial: false }));
}
// 9. The practice API from the emulator, by two names (Sections 3.2.5 and 3.17)
for (const host of ['localhost', '10.0.2.2']) {
try {
const res = await fetch(`http://${host}:8150/books`);
console.log(host, res.status, (await res.json()).total);
} catch (e) {
console.log(host, String(e));
}
}
// 10. Three sorts of five titles (Section 3.28.7)
const titles = ['b', 'Á', 'a', 'B', 'á'];
const byKey = [...titles].sort((x, y) =>
(x.toLowerCase() < y.toLowerCase() ? -1 : x.toLowerCase() > y.toLowerCase() ? 1 : 0));
console.log([...titles].sort().join(''), [...titles].sort(new Intl.Collator('en').compare)
.join(''), byKey.join(''));