← Walleye Capital Interview Insights

Walleye Capital·Software Engineer·Technical Phone Screen·Intermediate

Intermediate
Jun 2026

Summary

Technical screen at Walleye Capital where they handed me a set of React files with bugs baked in and asked me to work through them live. Eight categories of issues, one after another. Not a vibe check, more like a gauntlet.

Questions Asked (8)

Q1

You're given a React component where a useEffect or useCallback has a stale closure. Identify the symptom, root cause, and minimal fix.

Root Cause AnalysisTechnical Trade-offs
Author's notes

This one I actually felt okay on.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by describing the symptom: the effect or callback captures outdated state/props, leading to incorrect behavior. Then explain the root cause: missing dependencies in the dependency array or a function recreated each render without proper memoization. Finally, propose the minimal fix: add the missing dependencies or wrap the function in useCallback with correct deps, and discuss trade-offs like potential infinite loops.

Pro tip: Mention that you can use the functional update form of setState to avoid needing state in the dependency array, which is often a cleaner fix. Also, note that ESLint's exhaustive-deps rule can catch these issues early.

1. Identify the symptom

Describe how the stale closure manifests: e.g., the effect uses an old value of a variable, or a callback references outdated props/state, causing bugs like incorrect API calls or UI not updating.

2. Diagnose the root cause

Explain that the closure captures variables from the render in which it was created. If dependencies are missing from useEffect or useCallback, the closure isn't recreated when those variables change, leading to stale values.

3. Propose the minimal fix

Add the missing dependencies to the dependency array. If a function is a dependency, wrap it in useCallback with its own correct dependencies, or move it inside the effect if it's only used there.

4. Discuss trade-offs and alternatives

Mention potential issues like infinite loops if dependencies change every render, and alternatives like using refs or functional updates to avoid dependencies altogether.

Key Points to Mention

  • Stale closures occur when a function captures variables from an outdated render.
  • useEffect and useCallback rely on dependency arrays to know when to recreate the closure.
  • Missing dependencies are the most common cause; ESLint's exhaustive-deps rule helps detect them.
  • Minimal fix: add missing dependencies, but beware of infinite loops if dependencies are unstable.
  • Alternative fixes: use functional updates for setState, useRef for mutable values, or move functions inside effects.
  • Trade-offs: adding dependencies may cause more frequent re-renders or effect runs; memoization with useCallback/useMemo can help.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q2

A component is mutating state directly instead of using immutable updates. Walk through how you'd spot it and fix it.

Root Cause AnalysisTechnical Trade-offs
Author's notes

Pretty standard React gotcha.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by describing how you would detect direct state mutation using debugging tools and code review, then explain the root cause and its impact. Next, outline a systematic fix using immutable update patterns and preventive measures like linting and testing.

Pro tip: Mention that you'd add a regression test to catch future mutations, and use Object.freeze in development to make mutations fail fast—this shows you think about long-term prevention, not just the immediate fix.

1. Detect the Mutation

Use React DevTools, Redux DevTools, or console logging to identify unexpected state changes. Look for direct assignments like state.property = value or array.push without creating a new copy.

2. Confirm the Root Cause

Trace the mutation to its source by reviewing the component's code, especially event handlers and reducers. Check if the state is being modified in place rather than returned as a new object.

3. Apply Immutable Updates

Replace direct mutations with immutable patterns: use spread operators, Object.assign, or libraries like Immer. For arrays, use concat, slice, or spread instead of push/splice.

4. Prevent Future Occurrences

Enforce immutability with ESLint rules (e.g., react/no-direct-mutation-state), enable strict mode, and use Object.freeze in development. Add unit tests that assert state immutability.

5. Verify the Fix

Re-run the application and tests to ensure the mutation is resolved and no new issues arise. Monitor performance to confirm the fix doesn't introduce regressions.

Key Points to Mention

  • Common symptoms: UI not re-rendering, stale data, or unexpected behavior in connected components.
  • Tools: React DevTools, Redux DevTools, console.log, and breakpoints in browser debugger.
  • Immutable update patterns: spread operator, Object.assign, Array.prototype.concat, and libraries like Immer or Immutable.js.
  • Trade-offs: Immutable updates can be more verbose and may have performance overhead, but they enable predictable state management and easier debugging.
  • Preventive measures: ESLint rules, Object.freeze in development, and unit tests that check for state mutation.
  • Root cause analysis: Understand why the mutation was introduced (e.g., lack of awareness, performance optimization attempt) to address underlying issues.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q3

List items in a component are using incorrect or unstable key props. What goes wrong and how do you fix it?

Root Cause Analysis
Author's notes

Using index as key when items can reorder.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by explaining the symptoms of unstable keys: unnecessary re-renders, lost component state, and performance issues. Then describe how to diagnose the problem by inspecting key values and finally present the fix: using stable, unique identifiers like IDs from data. Emphasize the importance of keys in React's reconciliation algorithm.

Pro tip: Mention that using array indices as keys is only acceptable for static lists that never change; otherwise, it's a common anti-pattern that can lead to subtle bugs. Also, highlight that keys should be stable, predictable, and unique among siblings.

1. Explain the purpose of keys

Keys help React identify which items have changed, been added, or removed. They are crucial for efficient and correct rendering of lists.

2. Describe what goes wrong

Unstable keys (e.g., random values, array indices for dynamic lists) cause React to re-render items unnecessarily, lose component state (like input values), and degrade performance.

3. Diagnose the issue

Inspect the list rendering code to see what key is used. Check if keys are unique, stable, and predictable. Use React DevTools to observe component re-mounting.

4. Fix the problem

Replace unstable keys with stable, unique identifiers from the data, such as database IDs. If no ID exists, generate a stable ID when the data is created.

5. Verify and prevent

Test the fix by ensuring state is preserved and re-renders are minimized. Add linting rules or code reviews to catch unstable keys early.

Key Points to Mention

  • React's reconciliation algorithm uses keys to match elements between renders.
  • Unstable keys can cause component state loss and unnecessary re-mounting.
  • Array indices as keys are problematic for dynamic lists (reordering, insertion, deletion).
  • Stable keys should be unique among siblings and consistent across renders.
  • Use data IDs or generate stable IDs if none exist.
  • Performance implications: extra re-renders and DOM updates.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q4

A component is causing a re-render storm due to unstable object or function references passed as props or through context. Debug it.

Root Cause AnalysisTechnical Trade-offsSystem Design
Author's notes

This was the one I felt least confident about live.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by explaining how to reproduce and measure the re-render storm using React DevTools Profiler and why unstable references cause unnecessary renders. Then walk through a systematic debugging process: identify the unstable props/context values, trace their origins, and apply stabilization techniques like useMemo, useCallback, or useRef. Finally, discuss trade-offs and prevention strategies.

Pro tip: Emphasize that not all re-renders are bad—focus on the ones that cause performance issues, and always measure before optimizing. Mention that React.memo and useCallback have costs, so use them judiciously.

1. Reproduce and Measure

Use React DevTools Profiler to record the re-render storm, identify which components re-render excessively, and confirm that unstable references are the cause.

2. Identify Unstable References

Inspect props and context values passed to the re-rendering components. Look for objects, arrays, or functions created inline or in render, which change identity on every render.

3. Trace Origins

Find where these unstable references are created. They could be in a parent component's render, in a custom hook, or in a context provider's value.

4. Stabilize References

Apply useMemo for objects/arrays, useCallback for functions, and useRef for stable mutable values. For context, memoize the value object or split contexts.

5. Verify and Prevent

Re-measure to confirm the storm is resolved. Discuss adding lint rules (e.g., react-hooks/exhaustive-deps) and code review practices to prevent recurrence.

Key Points to Mention

  • React's reconciliation and how referential equality affects memoization (React.memo, PureComponent).
  • Common sources of unstable references: inline object/array literals, inline arrow functions, and new object instances in context providers.
  • Tools: React DevTools Profiler, why-did-you-render, and console logs to track renders.
  • Stabilization techniques: useMemo, useCallback, useRef, and moving static values outside the component.
  • Context optimization: memoizing the context value, splitting contexts, or using a state management library.
  • Trade-offs: memoization has memory and performance costs; overuse can lead to complexity and bugs.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q5

There's an async race condition in a useEffect. A fetch kicks off, the component unmounts or re-renders before it resolves, and stale results get applied. How do you handle it?

Root Cause AnalysisTechnical Trade-offs
Author's notes

Cleanup function returning from useEffect, set a cancelled flag or use AbortController.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by explaining the root cause: async operations in useEffect can resolve after the component unmounts or re-renders, leading to stale state updates. Then present a structured solution using cleanup functions and cancellation, and discuss trade-offs between different approaches. Finally, emphasize best practices for robust async handling in React.

Pro tip: Mention that while AbortController is ideal for fetch, you should also use an 'isMounted' flag or a ref to guard state updates, as not all async operations support cancellation. This shows you understand the nuances beyond just fetch.

1. Identify the root cause

Explain that useEffect runs after render, and if an async operation resolves after the component unmounts or before the next effect runs, it can call setState on an unmounted component or apply outdated data.

2. Use cleanup functions

Return a cleanup function from useEffect that cancels the async operation or sets a flag to ignore the result. This prevents state updates after unmount or before the next effect.

3. Implement cancellation

For fetch, use AbortController to cancel the request. For other async operations, use a boolean flag (e.g., isMounted) or a ref to track if the component is still mounted and the effect is current.

4. Discuss trade-offs

Compare approaches: AbortController is clean but only works with fetch; flags are universal but don't cancel the underlying operation. Consider using libraries like React Query that handle this automatically.

5. Summarize best practices

Conclude that the best solution depends on the async operation, but always include cleanup to avoid memory leaks and stale updates. Mention that React 18's strict mode double-invokes effects, making cleanup even more critical.

Key Points to Mention

  • AbortController for fetch cancellation
  • Cleanup function in useEffect
  • isMounted flag or ref to guard state updates
  • Stale closures and dependency array
  • React 18 strict mode double-invocation
  • Trade-offs between cancellation and ignoring results

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q6

A form input is switching between controlled and uncontrolled. What's the bug and what's the fix?

Root Cause Analysis
Author's notes

Passing undefined as the value prop initially, then setting it to a string later.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by defining what controlled and uncontrolled inputs are in React, then explain the common causes of switching (e.g., value prop toggling between undefined and a value). Describe the bug symptoms (React warning, lost focus, stale state) and provide a clear fix: ensure the input is consistently controlled by always providing a defined value and an onChange handler, or consistently uncontrolled with defaultValue.

Pro tip: Mention that the switch often happens when initial state is undefined and later set, and that using a fallback like `value={value ?? ''}` can prevent the switch while still allowing the input to be cleared. Also note that this is a common issue in forms with async data loading.

1. Define controlled vs uncontrolled

Explain that a controlled input has its value driven by React state via the `value` prop, while an uncontrolled input manages its own state internally, optionally with `defaultValue`.

2. Identify the switch

Describe how an input switches when the `value` prop changes from undefined to defined (or vice versa) during the component's lifecycle, often due to state initialization or async updates.

3. Explain the bug symptoms

Mention React's warning about switching, potential loss of focus, cursor jumping, and inconsistent state where the input's displayed value doesn't match React state.

4. Provide the fix

Recommend choosing one approach: either always controlled (initialize state to empty string, always pass `value` and `onChange`) or always uncontrolled (use `defaultValue` and refs). If controlled, ensure the value is never undefined.

5. Prevent future occurrences

Suggest using default values in state initialization, avoiding conditional `value` props, and using linters or TypeScript to catch potential undefined values.

Key Points to Mention

  • React warning: 'A component is changing an uncontrolled input to be controlled'
  • Common cause: initial state is undefined, then set to a value after data fetch
  • Fix: initialize state with empty string or use `value={value ?? ''}`
  • Alternative: use uncontrolled with `defaultValue` and refs if you don't need controlled behavior
  • Impact: lost focus, cursor jumping, and inconsistent UI state
  • Best practice: decide early and be consistent; use controlled for dynamic forms

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q7

Conditional rendering using && is showing a 0 on screen instead of nothing. Why does this happen and how do you fix it?

Root Cause Analysis
Author's notes

Because 0 is falsy but still a renderable value in JSX.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Explain that JavaScript's && operator returns the first falsy operand, and when that operand is 0, React renders it as text. Then describe the fix: use a ternary with null, or explicitly coerce the condition to a boolean (e.g., !!count && ...).

Pro tip: Mention that this is a common pitfall in React and that using a ternary with null is often preferred for clarity, but if you stick with &&, ensure the left side is always a boolean to avoid unexpected renders.

1. Identify the root cause

Explain that in JavaScript, the && operator returns the value of the first falsy operand, not necessarily a boolean. If the left side is 0, it returns 0, which React renders as '0'.

2. Show the problematic code

Provide a simple example: `{count && <Component />}` where count is 0. This renders '0' instead of nothing.

3. Present the fix

Offer two solutions: (1) Use a ternary: `{count ? <Component /> : null}`; (2) Coerce to boolean: `{!!count && <Component />}` or `{Boolean(count) && <Component />}`.

4. Discuss trade-offs

Mention that the ternary is more explicit and avoids the issue entirely, while the double negation is concise but may be less readable. Choose based on team style.

5. Prevent future occurrences

Suggest using TypeScript to enforce boolean types for conditions, or linting rules to catch non-boolean && expressions in JSX.

Key Points to Mention

  • JavaScript's && operator returns the first falsy operand, not a boolean.
  • React renders numbers, so 0 becomes visible text.
  • Fix with ternary: `condition ? <Component /> : null`.
  • Fix with boolean coercion: `!!condition && <Component />`.
  • TypeScript can help by ensuring conditions are boolean.
  • This is a common React pitfall, often caught in code review.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q8

An event handler isn't firing correctly due to a binding issue or prop-drilling mistake. Identify and fix it.

Root Cause AnalysisTechnical Trade-offs
Author's notes

Vague prompt honestly.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by systematically narrowing down the issue: verify the event handler is correctly bound and that props are passed down without breaks. Then, inspect the component hierarchy and use debugging tools to trace the data flow and event propagation. Finally, propose a fix that addresses the root cause and prevents similar issues.

Pro tip: Demonstrate proactive debugging by mentioning specific tools like React DevTools or browser event listeners, and emphasize writing a regression test to ensure the fix holds.

1. Reproduce and Isolate

Confirm the bug by reproducing it in a controlled environment, then isolate the component or handler causing the issue.

2. Inspect Binding and Props

Check if the event handler is properly bound (e.g., using arrow functions or .bind) and verify that props are passed correctly through all intermediate components.

3. Trace Data Flow

Use debugging tools to trace the event from trigger to handler, ensuring no prop-drilling mistakes or context issues interrupt the flow.

4. Implement and Verify Fix

Apply the appropriate fix (e.g., correct binding, use context, or lift state) and verify the handler fires as expected.

5. Prevent Recurrence

Add tests or linting rules to catch similar binding or prop-drilling issues in the future.

Key Points to Mention

  • Binding methods in class components vs. arrow functions in functional components
  • Prop-drilling and alternatives like Context API or state management libraries
  • Using React DevTools to inspect component props and event handlers
  • Event propagation and potential stopPropagation issues
  • Writing unit tests for event handlers
  • Code review practices to catch binding mistakes

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.