【问题标题】:React storing Ref elements in ReduxReact 在 Redux 中存储 Ref 元素
【发布时间】:2020-11-29 04:17:33
【问题描述】:

你会如何在 Redux 中存储 Ref 元素,你会这样做吗?

我有一个包含一些表单元素的组件,如果用户离开页面并返回,我需要存储用户在表单中选择的字段的状态。

我尝试像这样在 Redux 中注册每个输入字段(我正在使用 Blueprint.js 中的 <InputGroup> 组件):

<InputGroup
  inputRef={(ref) => { dispatch(addRefToState(ref)) }}
  ...more props...
/>

这导致了循环 JSON 引用错误,因为 Redux 将 ref 元素序列化为 JSON 以便将其保存到 localStorage。然后我尝试使用我在 Stackoverflow 上找到的 sn-p 对对象进行“安全”字符串化,在将对象转换为 JSON 之前删除所有循环引用。这种方法很有效,但是 Ref 元素仍然很大,以至于存储在 state 中的 3-5 个 refs 变成了 3MB localStorage,我的浏览器开始变得非常缓慢。此外,我担心我是否可以实际使用该 Ref 对象来引用我的组件,知道我本质上修改了 Ref 对象。我还没有尝试过,因为字符串化对象的性能很差。

我正在考虑放弃“React 方式”,只在每个组件上添加唯一的 ID,将它们存储在 Redux 中并使用 document.querySelector 迭代 DOM,以便在页面加载时聚焦正确的元素。但这感觉就像一个黑客。你会怎么做呢?

【问题讨论】:

    标签: reactjs react-redux react-ref


    【解决方案1】:

    我不确定我是否会将它们用于此目的,但它不会是第一个这样做的方法。

    拥有一个 React 状态来存储焦点表单元素的唯一标识符是非常好的。每个表单元素,或者一般的任何元素,都可以有一个唯一的标识符,它可以是一个字符串。您可以将它们保存在应用程序的 redux 存储中,以任何持久性(如 Web 存储)。

    当您离开时,您可以使用 React 效果将该状态提交到您的 redux 存储或持久性。

        const [lastFocusedElementId, setLastFocusedElementId] = useState();
        
        useEffect(() => {
          // here you can get last focused element id from props, or from directly storage etc, previously if any
          if(props.lastFocusedElID) {
            setLastFocusedElementId(props.lastFocusedElID);
          }
          // here in return you commit last focused id
          return saveLastFocusedElementID(lastFocusedElementId) // an action creator that saves to the redux store before every rerender of component and before unmount
        }, [props.lastFocusedElID]);
    

    或者

    const [lastFocusedElementId, setLastFocusedElementId] = useState();
    
    useEffect(() => {
      const lastFocusedElID = window.localStorage.getItem(lastFocusedElementId);
      if (lastFocusedElID) {
        setLastFocusedElementId(lastFocusedElID);
      }
      return window.localStorage.setItem('lastFocusedElementId', lastFocusedElementId);
    }, []);
    

    更不用说您需要在要设置最后一个焦点元素 ID 的表单元素上使用 onFocus。 Id 可以在您选择的属性上,可以是id 属性,或者您可以使用data-* 属性。我在这里显示了id 和 data-id。

    <input onFocus={e => setLastFocusedElementId(e.target.id)} />
    <input onFocus={e => setLastFocusedElementId(e.dataset.id)} />
    

    当您重新打开具有该表单元素的页面时,还需要一种方法将最后一个焦点元素与您选择的源中的数据集中在一起。您可以为每个元素添加autoFocus 属性,例如

    <input autoFocus={"elementID"===lastFocusedElementId} />
    

    最后,如果您的用户离开表单页面而没有关注任何元素,您可能希望将 id 设置为空字符串等基本值。在这种情况下,您需要使用带有 onBlur 处理程序的模糊事件。

    【讨论】:

    • 谢谢,这与我考虑改用的方法非常相似。我看看我能不能让它工作。
    • 不要犹豫,如果你关心的方式,它是完美的 React 方式,虽然相反的方式没有错。同样,上述方式也不需要您以前遇到过的大量数据。虽然我可能需要一些调整,但也许有一些错误。
    猜你喜欢
    • 1970-01-01
    • 2020-10-12
    • 2021-07-18
    • 1970-01-01
    • 2022-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-22
    相关资源
    最近更新 更多