简体   繁体   English

如何将 promise 中的值传递给 react native 的组件 prop?

[英]How do I pass a value from a promise to a component prop in react native?

Edit: I don't understand the reason for downvotes, this was a good question and no other questions on this site solved my issue.编辑:我不明白投反对票的原因,这是一个很好的问题,这个网站上没有其他问题解决了我的问题。 I simply preloaded the data to solve my issue but that still doesn't solve the problem without using functional components.我只是预先加载了数据来解决我的问题,但如果不使用功能组件,这仍然无法解决问题。

I'm trying to pass users last message into the ListItem subtitle prop but I can't seem to find a way to return the value from the promise/then call.我正在尝试将用户最后一条消息传递给 ListItem 字幕道具,但我似乎无法找到从承诺/然后调用返回值的方法。 It's returning a promise instead of the value which gives me a "failed prop type".它返回 promise 而不是给我“失败的道具类型”的值。 I thought about using a state but then I don't think I could call the function inside the ListItem component anymore.我考虑过使用 state 但后来我认为我不能再在 ListItem 组件中调用 function 了。

  getMsg = id => {
    const m = fireStoreDB
      .getUserLastMessage(fireStoreDB.getUID, id)
      .then(msg => {
        return msg;
      });
    return m;
  };

  renderItem = ({ item }) => (
    <ListItem
      onPress={() => {
        this.props.navigation.navigate('Chat', {
          userTo: item.id,
          UserToUsername: item.username
        });
      }}
      title={item.username}
      subtitle={this.getMsg(item.id)} // failed prop type
      bottomDivider
      chevron
    />
  );

You could only do it that way if ListItem expected to see a promise for its subtitle property, which I'm guessing it doesn't.如果ListItem期望看到 promise 的subtitle属性,你只能这样做,我猜它不会。 ;-) (Guessing because I haven't played with React Native yet. React , but not React Native.) ;-)(猜测是因为我还没有玩过 React Native。 React ,但不是 React Native。)

Instead, the component will need to have two states:相反,组件需要有两种状态:

  • The subtitle isn't loaded yet字幕还没加载
  • The subtitle is loaded字幕已加载

...and render each of those states. ...并渲染每个状态。 If you don't want the component to have state, then you need to handle the async query in the parent component and only render this component when you have the information it needs.如果您不希望该组件具有 state,那么您需要在父组件中处理异步查询,并且仅在您拥有该组件所需的信息时才呈现组件。

If the 'last message' is something specific to only the ListItem component and not something you have on hand already, you might want to let the list item make the network request on its own.如果“最后一条消息”是特定于ListItem组件的内容,而不是您手头已有的内容,您可能希望让列表项自己发出网络请求。 I would move the function inside ListItem .我会将 function 移动到ListItem内。 You'll need to set up some state to hold this value and possibly do some conditional rendering.您需要设置一些 state 来保存此值,并可能进行一些条件渲染。 Then you'll need to call this function when the component is mounted.然后您需要在安装组件时调用此 function。 I'm assuming you're using functional components, so useEffect() should help you out here:我假设您正在使用功能组件,所以useEffect()应该在这里帮助您:

//put this is a library of custom hooks you may want to use
//  this in other places
const useIsMounted = () => {
  const isMounted = useRef(false);
  useEffect(() => {
    isMounted.current = true;
    return () => (isMounted.current = false);
  }, []);
  return isMounted;
};

const ListItem = ({
  title,
  bottomDivider,
  chevron,
  onPress,
  id, //hae to pass id to ListItem
}) => {
  const [lastMessage, setLastMessage] = useState(null);
  const isMounted = useIsMounted();
  React.useEffect(() => {
    async function get() {
      const m = await fireStoreDB.getUserLastMessage(
        fireStoreDB.getUID,
        id
      );
      //before setting state check if component is still mounted
      if (isMounted.current) {
        setLastMessage(m);
      }
    }
    get();
  }, [id, isMounted]);

  return lastMessage ? <Text>DO SOMETHING</Text> : null;
};

I fixed the issue by using that promise method inside another promise method that I had on componentDidMount and added user's last message as an extra field for all users.我通过在另一个 promise 方法中使用该 promise 方法解决了这个问题,该方法是我在 componentDidMount 上拥有的,并将用户的最后一条消息添加为所有用户的额外字段。 That way I have all users info in one state to populate the ListItem.这样我就可以在一个 state 中拥有所有用户信息来填充 ListItem。

  componentDidMount() {
    fireStoreDB
      .getAllUsersExceptCurrent()
      .then(users =>
        Promise.all(
          users.map(({ id, username }) =>
            fireStoreDB
              .getUserLastMessage(fireStoreDB.getUID, id)
              .then(message => ({ id, username, message }))
          )
        )
      )
      .then(usersInfo => {
        this.setState({ usersInfo });
      });
  }

  renderItem = ({ item }) => (
    <ListItem
      onPress={() => {
        this.props.navigation.navigate('Chat', {
          userTo: item.id,
          UserToUsername: item.username
        });
      }}
      title={item.username}
      subtitle={item.message}
      bottomDivider
      chevron
    />
  );

the getMsg method is async, you could do as the following, as the HMR says the await still returns a promise, after I read an article ( https://medium.com/dailyjs/javascript-promises-zero-to-hero-plus-cheat-sheet-64d75051cffa ), and do some experiment. getMsg 方法是异步的,您可以执行以下操作,因为 HMR 说等待仍然返回 promise,在我阅读了一篇文章( https://medium.com/dailyjs/javascript-promises-zero-to-hero- plus-cheat-sheet-64d75051cfa ),并做一些实验。 the promise can return value. promise 可以返回值。

fetchData = () => {
  return new Promise((resolve, reject) => {
  setTimeout(function() {
    resoleve(2)
  }, 300);
}).then(() => {
  return 3
});
}

let a = await this.fetchData()
alert(a);

the a is 3. and you can continue handle the reponse in the call method.like the following code.if it don return value. a 为 3。您可以继续在调用方法中处理响应。如以下代码。如果它不返回值。 I think the fireStoreDB.getUserLastMessage(id) do not return anything.我认为fireStoreDB.getUserLastMessage(id)不返回任何内容。

getMsg = (id) => {
        const m = fireStoreDB.getUserLastMessage(id)
       .then(response => return response)
        return m;
         };

or you can realize the same effecu use the setState或者您可以使用 setState 实现相同的效果

//firstly you should define the var
this.state ={{
   m:"'
}}

// then update it when the data return
getMsg = id => {
        fireStoreDB
          .getUserLastMessage(fireStoreDB.getUID, id)
          .then(msg => {
            this.setState({
                 m:msg
             })
          }).catch(error => {
               // handle the error
            })
      };
// then use it in the item
...
subTitle = {this.state.m)
...

You could use async and await你可以使用asyncawait

getMsg = async (id) => await fireStoreDB.getUserLastMessage(fireStoreDB.getUID, id)

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

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