繁体   English   中英

我如何从我的反应 state 返回 object

[英]How do i return an object from my react state

我正在尝试从下面的代码中从集合中找到一个项目,以更新我的反应组件,propertState object 不是空的,它包含一个我已在控制台记录的列表,但是当我控制台记录从我的findProperty function 返回的值...我正在尝试使用该值更新我的 localState,以便我的组件可以呈现正确的数据。

    const PropertyComponent = () => {
        const { propertyId } = useParams();
    
        const propertyState: IPropertiesState = useSelector(
            propertiesStateSelector
        );
    
        const[property, setProperty] = useState()
    
        const findProperty = (propertyId, properties) => {
            let propertyReturn;
            for (var i=0; i < properties.length; i++) {
                if (properties[i].propertyId === propertyId) {
                    propertyToReturn = properties[i];
                    break;
                }
            }
            setProperty(propertyReturn)
            return propertyReturn;
        }
    
        const foundProperty = findProperty(propertyId, propertyState.properties);
    
        return (<>{property.propertyName}</>)
    }

export default PropertyComponent

当您根据外部数据源查找数据和更新状态时,您应该考虑一些事项 --useParams--

我将尝试通过将您的代码分成小块来解释解决方案

    const PropertyComponent = () => {
        const { propertyId } = useParams();

部分A:考虑useParams是一个连接到路由器的钩子,这意味着您的组件可能是反应性的,并且每次 URL 中的参数更改时都会更改。 您的参数可能未定义或字符串取决于参数是否存在于您的 URL

const propertyState: IPropertiesState = useSelector(
            propertiesStateSelector
        );

部分B: useSelector是另一个属性,它可以让您的组件对与该选择器相关的更改做出反应。 您的选择器可能会根据您的选择逻辑返回 undefined 或其他内容。

const[property, setProperty] = useState()

部分 C:您的 state 在第一次渲染中开始为undefined

到目前为止,我们刚刚发现了 3 段可能以未定义或未定义开头的代码。

const findProperty = (propertyId, properties) => {
            let propertyReturn;
            for (var i=0; i < properties.length; i++) {
                if (properties[i].propertyId === propertyId) {
                    propertyToReturn = properties[i];
                    break;
                }
            }
            setProperty(propertyReturn)
            return propertyReturn;
        }
    
        const foundProperty = findProperty(propertyId, propertyState.properties);

部分D:这是开始出现更多问题的时候,你告诉你的代码在每次渲染中都会创建一个 function findProperty并使用 state --setProperty-- 的设置器添加一些内部依赖项。

我建议您通过简单的步骤考虑您想要执行的操作,然后您就可以了解每段代码属于哪里。

让我们细分最后一段代码--D部分--但在步骤中,您想要:

  1. 找东西。
  2. 如果您有一个可以在哪里查找的数组和一个属性,则应该进行查找。
  3. 结果我想通知我的组件发现了一些东西。

步骤 1 和 2 可能发生在您的组件外部定义的 function 中:

const findProperty = (propertyId, properties) => properties.find((property) => property.propertyId === propertyId)

注意:我冒昧地通过简化您的发现 function 来修改您的代码。

现在我们需要做最重要的一步,让你的组件在正确的时间做出反应

const findProperty = (propertyId, properties) => properties.find((property) => property.propertyId === propertyId)

const PropertyComponent = () => {
        const { propertyId } = useParams();
    
        const propertyState: IPropertiesState = useSelector(
            propertiesStateSelector
        );
         
        const[property, setProperty] = useState({ propertyName: '' }); // I suggest to add default values to have more predictable returns in your component

        /**
         * Here is where the magic begins and we try to mix all of our values in a consistent way (thinking on the previous pieces and the potential "undefined" values) We need to tell react "do something when the data is ready", for that reason we will use an effect
         */

        useEffect(() => {
          // This effect will run every time that the dependencies --second argument-- changes, then you react afterwards.
          if(propertyId, propertyState.properties) {
              const propertyFound = findProperty(propertyId, propertyState.properties);
              if(propertyFound){ // Only if we have a result we will update our state.
                setProperty(propertyFound);
              }
          }
        }, [propertyId, propertyState.properties])
 

        return (<>{property.propertyName}</>)
    }

export default PropertyComponent

我认为这样你的意图可能更直接,但肯定还有其他方法可以做到这一点。 根据您的意图,您的代码应该有所不同,例如我有一个问题:

这个组件的目的是什么? 如果它只是为了获取属性,你可以做一个派生的 state ,一个更复杂的选择器。 例如

function propertySelectorById(id) {
   return function(store) {
      const allProperties = propertiesStateSelector(store);
      const foundProperty = findProperty(id, allProperties);
      if( foundProperty ) {
         return foundProperty;
      } else {
         return null; // Or empty object, up to you
      }
   }
}

然后你可以在任何使用 useParam 的组件中使用它,或者只是创建一个简单的 hook 例如


function usePropertySelectorHook() {
   const { propertyId } = useParams();
   const property = useSelector(propertySelectorById(propertyId));

   return property;
}

之后你可以在任何组件中使用它


functon AnyComponent() {
  const property = usePropertySelectorHook();

  return <div> Magic {property}</div>
}

注意:我没有测试所有代码,我直接在评论中写了它,但我认为应该可以。

像这样我认为有更多的方法可以解决这个问题,但现在已经足够了,希望这对你有所帮助。

你试试这个:

const found = propertyState.properties.find(element => element.propertyId === propertyId);
setProperty(found);

而不是所有 function findProperty

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM