Get ref from connected redux component withStyles

余生长醉 提交于 2019-12-11 05:26:07

问题


I have this export of a working component:

export default connect(
    mapStateToProps, actions,
    null, { withRef: true, forwardRef: true }
  )(withTheme()(withStyles(styles)(MainMenu)));

And its call:

<MainMenu 
  ref={(connectedMenu) => this.menuRef = connectedMenu.getWrappedInstance()} 
  user={user} 
/>

I've expected to get a MainMenu ref, but I keep getting WithTheme object instead.

I've also tried to get through innerRef, but got the following errors:

TypeError: connectedMenu.getWrappedInstance is not a function
TypeError: Cannot read property 'getWrappedInstance' of null

Before all of that I've tried that React.createRef() format, but it didn't worked.

How do I get this ref?


回答1:


Assuming you are using v4 of Material-UI, your syntax for withTheme is incorrect. In v4 the first set of parentheses was removed.

Instead of

withTheme()(YourComponent)

you should have

withTheme(YourComponent)

Below is code from a modified version of the react-redux todo list tutorial that shows the correct syntax. I've included here the two files that I changed (TodoList.js and TodoApp.js), but the sandbox is a fully working example.

In TodoApp, I use the ref on TodoList to get and display its height. The displayed height will only get updated if TodoApp re-renders, so I've included a button to trigger a re-render. If you add a couple todos to the todo list, and then click the re-render button, you will see that the new height of the list is displayed (showing that the ref is fully working).

In TodoList, I'm using withStyles to add a blue border around the todo list to show that withStyles is working, and I'm displaying the primary color from the theme to show that withTheme is working.

TodoList.js

import React from "react";
import { connect } from "react-redux";
import Todo from "./Todo";
import { getTodosByVisibilityFilter } from "../redux/selectors";
import { withStyles, withTheme } from "@material-ui/core/styles";
import clsx from "clsx";

const styles = {
  list: {
    border: "1px solid blue"
  }
};
const TodoList = React.forwardRef(({ todos, theme, classes }, ref) => (
  <>
    <div>theme.palette.primary.main: {theme.palette.primary.main}</div>
    <ul ref={ref} className={clsx("todo-list", classes.list)}>
      {todos && todos.length
        ? todos.map((todo, index) => {
            return <Todo key={`todo-${todo.id}`} todo={todo} />;
          })
        : "No todos, yay!"}
    </ul>
  </>
));

const mapStateToProps = state => {
  const { visibilityFilter } = state;
  const todos = getTodosByVisibilityFilter(state, visibilityFilter);
  return { todos };
};
export default connect(
  mapStateToProps,
  null,
  null,
  { forwardRef: true }
)(withTheme(withStyles(styles)(TodoList)));

TodoApp.js

import React from "react";
import AddTodo from "./components/AddTodo";
import TodoList from "./components/TodoList";
import VisibilityFilters from "./components/VisibilityFilters";
import "./styles.css";

export default function TodoApp() {
  const [renderIndex, incrementRenderIndex] = React.useReducer(
    prevRenderIndex => prevRenderIndex + 1,
    0
  );
  const todoListRef = React.useRef();
  const heightDisplayRef = React.useRef();
  React.useEffect(() => {
    if (todoListRef.current && heightDisplayRef.current) {
      heightDisplayRef.current.innerHTML = ` (height: ${
        todoListRef.current.offsetHeight
      })`;
    }
  });
  return (
    <div className="todo-app">
      <h1>
        Todo List
        <span ref={heightDisplayRef} />
      </h1>
      <AddTodo />
      <TodoList ref={todoListRef} />
      <VisibilityFilters />
      <button onClick={incrementRenderIndex}>
        Trigger re-render of TodoApp
      </button>
      <div>Render Index: {renderIndex}</div>
    </div>
  );
}



来源:https://stackoverflow.com/questions/57191025/get-ref-from-connected-redux-component-withstyles

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!