sas*_*nov 8 reactjs material-ui react-redux react-router-dom
我正在尝试在连接到 react-redux 的组件中使用 ref
我试过这个解决方案。
connect(null, null, null, {forwardRef: true})(myCom)
<myCom ref={ref => this.myCom = ref} />
根据 react-redux 文档,这很好用,但是现在当我尝试使用
withRouter 同时我收到一个错误: 
不能给函数组件提供 refs。尝试访问此引用将失败。你的意思是使用 React.forwardRef() 吗?
所以我尝试过的最终导出代码导致了上述错误
export default connect(null, null, null, { forwardRef: true })(withRouter(withStyles(styles)(myCom)));
Run Code Online (Sandbox Code Playgroud)
注意:withStyles 不会引起任何问题,因为我尝试仅删除 withRouter,问题已解决。
有没有办法解决这个问题?
为了将 ref 传递给由withRouter您包装的组件,您需要将其称为wrappedComponentRef。我建议使用withRouter最外层的包装器,因此您的示例如下所示:
withRouter(connect(null, null, null, {forwardRef: true})(myCom));
Run Code Online (Sandbox Code Playgroud)
<myCom wrappedComponentRef={ref => this.myCom = ref} />
Run Code Online (Sandbox Code Playgroud)
以下示例和描述改编自我的一个相关答案:Get ref from connected redux component withStyles
下面是来自react-redux 待办事项列表教程的修改版本的代码,显示了正确的语法。我在此处包含了我更改的两个文件(TodoList.js 和 TodoApp.js),但沙箱是一个完全有效的示例。
在 中TodoApp,我使用 ref(通过wrappedComponentRef属性)TodoList来获取并显示其高度。显示的高度只会在TodoApp重新渲染时更新,所以我添加了一个按钮来触发重新渲染。如果在待办事项列表中添加几个待办事项,然后单击重新渲染按钮,您将看到列表的新高度显示出来(表明 ref 已完全工作)。
在 中TodoList,我使用withStyles在待办事项列表周围添加蓝色边框来显示它withStyles正在工作,并且我正在显示主题的主要颜色以表明它withTheme正在工作。我还显示location对象 fromwithRouter以证明它withRouter正在工作。
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";
import { withRouter } from "react-router-dom";
const styles = {
  list: {
    border: "1px solid blue"
  }
};
const TodoList = React.forwardRef(
  ({ todos, theme, classes, location }, ref) => (
    <>
      <div>Location (from withRouter): {JSON.stringify(location)}</div>
      <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 withRouter(
  connect(
    mapStateToProps,
    null,
    null,
    { forwardRef: true }
  )(withTheme(withStyles(styles)(TodoList)))
);
Run Code Online (Sandbox Code Playgroud)
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 wrappedComponentRef={todoListRef} />
      <VisibilityFilters />
      <button onClick={incrementRenderIndex}>
        Trigger re-render of TodoApp
      </button>
      <div>Render Index: {renderIndex}</div>
    </div>
  );
}
Run Code Online (Sandbox Code Playgroud)
        使用compose方法并尝试这样的事情
const enhance = compose(
  withStyles(styles),
  withRouter,
  connect(mapStateToProps, null, null, { forwardRef: true })
)
Run Code Online (Sandbox Code Playgroud)
并在导出组件之前使用它
export default enhance(MyComponent)
Run Code Online (Sandbox Code Playgroud)
        |   归档时间:  |  
           
  |  
        
|   查看次数:  |  
           6335 次  |  
        
|   最近记录:  |