正常情况下,有了props,我们就可以写
componentDidUpdate(oldProps) {
if (oldProps.foo !== this.props.foo) {
console.log('foo prop changed')
}
}
Run Code Online (Sandbox Code Playgroud)
为了检测道具的变化。
但是如果我们使用React.createRef()
,我们如何检测 ref 何时更改为新组件或 DOM 元素?React 文档并没有真正提及任何内容。
铁,
class Foo extends React.Component {
someRef = React.createRef()
componentDidUpdate(oldProps) {
const refChanged = /* What do we put here? */
if (refChanged) {
console.log('new ref value:', this.someRef.current)
}
}
render() {
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
我们是否应该自己实现某种旧价值的东西?
铁,
class Foo extends React.Component {
someRef = React.createRef()
oldRef = {}
componentDidMount() {
this.oldRef.current = this.someRef.current
}
componentDidUpdate(oldProps) {
const …
Run Code Online (Sandbox Code Playgroud) 下面是一个可变 ref 的示例,该示例存储来自Overreacted 博客的当前回调:
function useInterval(callback, delay) {
const savedCallback = useRef();
// update ref before 2nd effect
useEffect(() => {
savedCallback.current = callback; // save the callback in a mutable ref
});
useEffect(() => {
function tick() {
// can always access the most recent callback value without callback dep
savedCallback.current();
}
let id = setInterval(tick, delay);
return () => clearInterval(id);
}, [delay]);
}
Run Code Online (Sandbox Code Playgroud)
然而,React Hook FAQ 指出不推荐使用该模式:
另请注意,此模式可能会导致并发模式出现问题。[...]
在任何一种情况下,我们都不推荐这种模式,只是为了完整起见在这里展示它。
我发现这种模式对于回调非常有用,但我不明白为什么它会在 FAQ 中出现危险信号。例如,客户端组件可以使用 …
为什么不能将 ref 传递给 React 中的功能组件?
与无法向其传递引用的类组件相比,函数组件有何不同?
为什么那不可能呢?
注意:我提出这个问题是因为我总是看到有关如何将 ref 与功能组件一起使用的解释,并且您需要使用fowardRef
,但没有人解释 React 如何处理功能组件,从而无法将 ref 传递给它,它总是解释如何去做,但从来没有解释为什么你需要这样做。
我正在尝试将节点从 ref 传递到上下文。但是因为我在第一次渲染后没有重新渲染,所以传递的节点是null
. 我想到了两种变体(但我认为它们不是最好的):
通过ref
而不是ref.current
. 但是在用例中,我将被迫使用类似的东西contextRef.current
而不是contextNode
.
使用状态(像firstRender
得到一个后)重新渲染的成分ref.current
。这似乎不是最优的。
什么是正确的(最好的?)方法?
import React, { createContext, createRef, useContext, useEffect } from "react";
import ReactDOM from "react-dom";
const Context = createContext(null);
const App = ({ children }) => {
const ref = createRef();
return (
<div ref={ref}>
<Context.Provider value={ref.current}>{children}</Context.Provider>
</div>
);
};
const Child = () => {
const contextNode = useContext(Context);
useEffect(() => {
console.log(contextNode);
});
return <div />; …
Run Code Online (Sandbox Code Playgroud) 您会如何在 Redux 中存储 Ref 元素?您会这样做吗?
我有一个包含一些表单元素的组件,如果用户离开页面并返回,我需要存储用户在表单中选择的字段的状态。
我尝试像这样在 Redux 中注册每个输入字段(我使用的<InputGroup>
是 Blueprint.js 中的组件):
<InputGroup
inputRef={(ref) => { dispatch(addRefToState(ref)) }}
...more props...
/>
Run Code Online (Sandbox Code Playgroud)
这导致了循环 JSON 引用错误,因为 Redux 正在将 ref 元素序列化为 JSON,以便将其保存到 localStorage。然后,我尝试使用我在 Stackoverflow 上找到的代码片段对对象进行“安全”字符串化,在将对象转换为 JSON 之前删除所有循环引用。这种方法可行,但 Ref 元素仍然很大,以至于存储在状态中的 3-5 个引用变成了 3MB 的 localStorage,并且我的浏览器开始变得非常慢。此外,我担心我是否可以实际使用该 Ref 对象来引用我的组件,因为我基本上修改了 Ref 对象。我还没有尝试过,因为字符串化对象的性能非常差。
我正在考虑放弃“React 方式”,只在每个组件上添加唯一的 ID,将这些 ID 存储在 Redux 中,并使用 document.querySelector 迭代 DOM,以便在加载页面时聚焦到正确的元素。但感觉就像是黑客攻击。你会怎样做呢?
我正在尝试使用 react 和 typescript 为我们的应用程序创建一个通用的文本输入组件。我希望它能够成为基于给定道具的输入元素或 textarea 元素。所以它看起来有点像这样:
import {TextArea, Input} from 'ourComponentLibrary'
export const Component = forwardRef((props, ref) => {
const Element = props.type === 'textArea' ? TextArea : Input
return (
<Element ref={ref} />
)
})
Run Code Online (Sandbox Code Playgroud)
这段代码工作正常。然而,当试图合并类型时,它变得有点冒险。ref 类型应该是HTMLInputElement
或HTMLTextAreaElement
基于传递的type
prop。在我的脑海中,它看起来像这样:
interface Props {
...
}
export const Component = forwardRef<
HTMLInputElement | HTMLTextAreaElement,
Props
>((props, ref) => {
...
});
Run Code Online (Sandbox Code Playgroud)
但是我知道这不完全是我需要的。因此,错误:
Type 'HTMLInputElement' is missing the following properties from type 'HTMLTextAreaElement': cols, rows, textLength, wrap …
根据 React 文档,将 ref 传递给子组件的正确方法如下:
import React from 'react';
const Input = React.forwardRef((props, ref) => {
React.useEffect(() => {
ref.current.focus();
}, []);
return <input type="text" ref={ref} />;
});
export default function App() {
const inputRef = React.createRef();
return (
<div>
<Input ref={inputRef} />
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我尝试将创建的 ref 作为普通 prop 以任何其他名称(然后是“ref”)传递,这也会按预期工作。
import React from 'react';
const Input = (props) => {
React.useEffect(() => {
props.inputRef.current.focus();
}, []);
return <input type="text" ref={props.inputRef} />;
};
export default function App() {
const inputRef …
Run Code Online (Sandbox Code Playgroud) 我正在做一些反应,并遇到了一个我无法解决自己的挑战。我在这里和其他地方搜索过,发现了标题相似的主题,但与我遇到的问题没有任何关系,所以我们开始:
所以我有一个数组,它将被映射到 React 组件中,通常如下所示:
export default ParentComponent = () => {
//bunch of stuff here and there is an array called arr
return (<>
{arr.map((item, id) => {<ChildComponent props={item} key={id}>})}
</>)
}
Run Code Online (Sandbox Code Playgroud)
但问题是,父元素中有一个状态,它存储当前选定的子组件之一的 id(我通过设置上下文并在子组件内设置此状态来做到这一点),然后问题是我必须引用当前选定的 ChildComponent 内部的节点。我可以毫无问题地转发引用,但我也想仅在当前选定的 ChildComponent 上分配引用,我想这样做:
export default ParentComponent = () => {
//bunch of stuff here and there is an array called arr and there's a state which holds the id of a selected ChildComponent called selectedObjectId
const selectedRef = createRef();
return (<>
<someContextProvider>
{arr.map((item, id) => …
Run Code Online (Sandbox Code Playgroud) 我正在创建一个组件,该组件将保存动态元素列表,出于样式原因,我需要将每个部分的标题保留在粘性导航菜单中。当用户上下滚动部分列表时,我需要应用样式规则,并将菜单导航中的同一部分带入视图,因此我尝试将scrollIntoView与菜单部分引用一起使用。
我的内部工作和逻辑似乎按预期工作,但是存在一个问题 - 除非我检查或在页面上使用刷新,否则scrollIntoView的函数不会在每次状态更改时执行
const scrollTo = (ref) => {
ref.current.scrollIntoView({ behavior: "smooth", inline: "center" });
};
Run Code Online (Sandbox Code Playgroud)
为了简单起见,我已将我的工作添加到此codesandbox中
任何帮助将不胜感激,因为我已经没有想法了。
谢谢
编辑:
如果我从scrollIntoViewOptions选项中删除行为参数中的“smooth”选项,滚动行为似乎会按预期工作。然而它看起来确实很神经质。
const scrollToMenu = (ref) => {
ref.current.scrollIntoView({ inline: "center", });
};
Run Code Online (Sandbox Code Playgroud) reactjs js-scrollintoview react-ref react-usememo react-scroll
在下面的函数中,我得到了带有属性的textarea对象current
.
这里,嵌套的解构与Start
和End
变量一起工作.但current
变量不起作用.
function someFunction({ current: { selectionStart: Start, selectionEnd: End } }, AppStateSetter) {
// do something with current, Start, and End
}
Run Code Online (Sandbox Code Playgroud) react-ref ×10
reactjs ×10
javascript ×4
react-hooks ×3
react-redux ×1
react-scroll ×1
typescript ×1