Получить ссылку из подключенного компонента redux со стилями

#javascript #reactjs #redux #material-ui

#reactjs #реагировать-redux #материал-пользовательский интерфейс

Вопрос:

У меня есть этот экспорт рабочего компонента:

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

И его вызов:

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

Я ожидал получить ссылку на MainMenu, но вместо этого я продолжаю получать с помощью объекта Theme.

Я также пытался пройти через innerRef, но получил следующие ошибки:

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

Перед всем этим я пробовал этот React.createRef() формат, но он не работал.

Как мне получить эту ссылку?

Ответ №1:

Предполагая, что вы используете версию 4 Material-UI, ваш синтаксис для withTheme неверен. В версии 4 первый набор круглых скобок был удален.

Вместо

 withTheme()(YourComponent)
  

у вас должно быть

 withTheme(YourComponent)
  

Ниже приведен код из модифицированной версии руководства по списку задач react-redux, который показывает правильный синтаксис. Я включил сюда два файла, которые я изменил (TodoList.js и TodoApp.js ), но песочница — это полностью рабочий пример.

В TodoApp я использую ссылку на TodoList , чтобы получить и отобразить ее высоту. Отображаемая высота будет обновляться только при TodoApp повторном рендеринге, поэтому я включил кнопку для запуска повторного рендеринга. Если вы добавите пару задач в список задач, а затем нажмете кнопку повторного рендеринга, вы увидите, что отображается новая высота списка (показывая, что ссылка полностью работает).

В TodoList я использую withStyles для добавления синей рамки вокруг списка задач, чтобы показать, что withStyles работает, и я отображаю основной цвет из темы, чтобы показать, что withTheme работает.

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 amp;amp; 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 amp;amp; 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>
  );
}
  

Редактировать приложение Todo с помощью Redux