Skip to content

Fix: How to safely access instance properties declared in a class component w#229

Open
obsofficer-ctrl wants to merge 1 commit intopiotrwitek:masterfrom
obsofficer-ctrl:fix/task-384723824
Open

Fix: How to safely access instance properties declared in a class component w#229
obsofficer-ctrl wants to merge 1 commit intopiotrwitek:masterfrom
obsofficer-ctrl:fix/task-384723824

Conversation

@obsofficer-ctrl
Copy link
Copy Markdown

Summary

This PR addresses: #108

Task: How to safely access instance properties declared in a class component with createRef
Platform: github

Changes

Solution: Safely Accessing Instance Properties with createRef on Connected Components

Analysis

The core problem is that React.createRef<Child>() creates a ref typed to the unwrapped Child class, but when you use connect()(Child), the exported component is a ConnectedComponentClass wrapper. TypeScript doesn't know that the ref on the connected component will actually point to the inner Child instance.

The solution is to use the WrappedComponentRef / ConnectedComponentClass instance type trick, or more cleanly: export the inner class separately and type the ref against the inner class directly, while using React.createRef<Child>() with the unwrapped class type.

Let me provide a complete working example that fits the repo's playground style.


Implementation

import React from 'react';
import { connect } from 'react-redux';

/**
 * SOLUTION: How to safely access instance properties on a connected component via createRef
 *
 * The key insight: export the inner class separately so you can type
 * React.createRef<ChildComponent>() against the *unwrapped* class.
 * The connected component forwards refs to the wrapped instance automatically
 * (React-Redux v6+ with forwardRef option, or simply relying on the fact that
 * class component refs resolve to the inner instance).
 *
 * For React-Redux, use the `{ forwardRef: true }` connect option (v7+) to
 * ensure the ref is forwarded through the HOC to the underlying class instance.
 */

// ─── Child ────────────────────────────────────────────────────────────────────

type ChildProps = {
  dispatch?: React.Dispatch<any>;
  greeting?: string;
};

// Export the bare class so parents can use it as the ref type
export class ChildComponent extends React.Component<ChildProps> {
  foo() {
    console.log('ChildComponent.foo() called');
  }

  render() {
    return <div>Child: {this.props.greeting}</div>;
  }
}

// Use { forwardRef: true } so t

## Testing

- [x] Code runs without errors
- [x] Tested against requirements
- [x] Code follows project conventions

---
*Submitted via automated workflow*

@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a common challenge in React-Redux applications involving TypeScript and refs. It provides a clear, type-safe pattern for accessing instance methods of a class component that has been wrapped by react-redux's connect higher-order component. By correctly configuring connect with forwardRef and structuring the component exports, the solution ensures that React.createRef resolves to the actual component instance, enabling reliable interaction with its properties and methods.

Highlights

  • Ref forwarding in React-Redux: Demonstrated how to safely access instance properties of a connected class component using React.createRef by exporting the inner component and leveraging the forwardRef option in connect.
  • TypeScript type safety: Provided a robust TypeScript solution that ensures correct type inference for refs pointing to wrapped components, preventing common type errors.
  • Playground example: Introduced a new playground example (connected-component-ref.tsx) to illustrate the solution in a practical, runnable context.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • playground\src\connected-component-ref.tsx
    • Added a new file connected-component-ref.tsx to the playground.
    • Implemented ChildComponent as an exported bare class.
    • Created a connected Child component using connect with forwardRef: true.
    • Developed a Parent component demonstrating how to use React.createRef() to access the ChildComponent instance.
Activity
  • The pull request was submitted via an automated workflow.
  • The author performed self-testing, confirming that the code runs without errors, meets requirements, and follows project conventions.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This PR adds a useful example for using forwardRef with react-redux's connect HOC. The implementation is correct and follows the intended pattern. I've added a couple of suggestions to further improve the code by applying some common React best practices for type safety and performance in class components.


// ─── Parent ───────────────────────────────────────────────────────────────────

export class Parent extends React.Component {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For better type safety, it's recommended to explicitly type the props for class components. Since the Parent component doesn't accept any props, you can define it as React.Component<{}>. Using React.Component without generics defaults props to any, which can hide potential bugs.

Suggested change
export class Parent extends React.Component {
export class Parent extends React.Component<{}> {

Comment on lines +54 to +59
bar() {
if (this.childRef.current) {
// ✅ No TypeScript error – .foo() is correctly typed
this.childRef.current.foo();
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To avoid creating a new function in the render method for the onClick handler, you can define bar as a class property using an arrow function. This binds this correctly and allows you to pass the method directly to onClick (i.e., <button onClick={this.bar}>). This is a common performance optimization in React class components. I've also made the method private as it's an internal helper.

Suggested change
bar() {
if (this.childRef.current) {
// ✅ No TypeScript error – .foo() is correctly typed
this.childRef.current.foo();
}
}
private bar = () => {
if (this.childRef.current) {
// ✅ No TypeScript error – .foo() is correctly typed
this.childRef.current.foo();
}
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant