简体   繁体   中英

ref does not exist on container component

I'm trying to call a function from a child component through a Connected Component (Container) from the parent.

When I try to reference the child component I get the error Property 'ref' does not exist on type 'IntrinsicAttributes & Pick<{ results: {}[]; }, never>'. Property 'ref' does not exist on type 'IntrinsicAttributes & Pick<{ results: {}[]; }, never>'.

Sorry for the wall of code that's about to follow, I tried to trim the code as much as possible.

Here's the parent component:

imports...

class App extends React.Component {
    searchBoxRef = createRef<SearchBox>();

    resetTextBox() {
        console.log("It's happening!")

        // if (this.searchBoxRef.current) {
        //     this.searchBoxRef.current.clearInput();
        // }
    }

    render() {
        return (
            <div>
                <div className="grid-container">
                    <div className="header">
                        <SearchBoxContainer ref={this.searchBoxRef} />
                    </div>
                    <FacetboxContainer resetAll={this.resetTextBox} />
                    <ResultsContainer/>
                </div>
            </div >
        )
    }
}

export default App;

The container component:

imports...

function getReturnType<RT>(expression: (...params: any[])=>RT): RT {
    return {} as RT;
}          

declare type SearchDispatchActions = FacetsAction | SuggestionsAction | InputAction

const mapDispatchToProps = (dispatch: redux.Dispatch<SearchDispatchActions>) => {
    return {
        *dispatch items*
    }
}

function mapStateToProps(state: Store.SearchState) {
    return {
        *props*
    }
}

export const stateProps = getReturnType(mapStateToProps);
export const dispatchProps = getReturnType(mapDispatchToProps);

export type PropsType = typeof stateProps & typeof dispatchProps;
type State = {};

const SearchBoxContainer = connect(mapStateToProps, mapDispatchToProps, null, { forwardRef: true })(SearchBox);

export { SearchBoxContainer }

And finally here's the Searchbox component

imports...

export type State = {
  searchInput: string;
};

class SearchBox extends React.Component<PropsType, State> {
  constructor(props: PropsType) {
    super(props);
    this.state = { searchInput: "" };
  }

  private searchRef = React.createRef<HTMLInputElement>();

  ...

  render() {
    ...

    return (
        ...
    );
  }
}

export default SearchBox;

Thanks for the help.

You were concerned about posting too much code, but I actually think you haven't provided enough! I'm not sure how you are executing the clearInput() and why you need a ref to the HTMLInputElement inside SearchBox at all, since I would think that you would clear the input by setting state.searchInput .

With Refs

Property 'ref' does not exist on type 'IntrinsicAttributes & Pick<{ results: {}[]; }, never>'.

This error tells you that you cannot pass the prop ref to the component SearchBox because ref is not defined as a prop. You can either:

  1. allow SearchBox to take a ref prop by creating a ForwardRefExoticComponent with the forwardRef function.
  2. pass a RefObject under any other prop name.

If the ultimate ref is to an HTMLInputElement , you can create the ref in App and pass it down through a prop called inputRef .

inputRef = useRef<HTMLInputElement>();
<SearchBoxContainer inputRef={this.inputRef} />
export type PropsType = typeof stateProps & typeof dispatchProps & {
  inputRef: React.RefObject<HTMLInputElement>
}

But if we start manipulating the value of the input directly from App when the value is also controlled by the state of SearchBox , you'll start to see why this is a bad design pattern.

Without Refs

Why don't we ditch the refs entirely and lift the state of the input text up into App ? Now SearchBox has no component state, and it handles everything through props text and onChangeText .

class App extends React.Component<{}, State> {
  state = { searchInput: "" };

  resetTextBox() {
    console.log("It's happening!");
    this.setState({ searchInput: "" });
  }

  render() {
    return (
      <div>
        <div className="grid-container">
          <div className="header">
            <SearchBoxContainer
              text={this.state.searchInput}
              onChangeText={(text) => this.setState({ searchInput: text })}
            />
          </div>
          <FacetboxContainer resetAll={this.resetTextBox} />
          <ResultsContainer />
        </div>
      </div>
    );
  }
}
export type PropsType = typeof stateProps & typeof dispatchProps & {
  text: string;
  onChangeText(text: string): void;
};

class SearchBox extends React.Component<PropsType> {
  render() {
    return (
      <input
        value={this.props.text}
        onChange={(e) => this.props.onChangeText(e.currentTarget.value)}
      />
    );
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM