如何在 React Native 中将 promise 中的值传递给组件 prop?

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

编辑:我不明白投反对票的原因,这是一个很好的问题,该站点上没有其他问题可以解决我的问题。我只是简单地预加载了数据来解决我的问题,但是如果不使用功能组件仍然无法解决问题。

我正在尝试将用户最后一条消息传递到 ListItem 字幕道具中,但我似乎无法找到 return 来自 promise/then 调用的值的方法。它是 return 一个承诺,而不是给我一个 "failed prop type" 的价值。我考虑过使用状态,但后来我认为我不能再调用 ListItem 组件内的函数了。

  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
    />
  );

如果 ListItem 希望看到其 subtitle 属性 的承诺,你只能这样做,我猜它不会。 ;-)(猜测是因为我还没有玩过 React Native。React,但不是 React Native。)

相反,组件需要有两种状态:

  • 字幕尚未加载
  • 字幕已加载

...并渲染每个状态。如果你不希望组件有状态,那么你需要在父组件中处理异步查询,只有当你有它需要的信息时才渲染 this 组件。

如果 'last message' 仅特定于 ListItem 组件而不是您手头已有的东西,您可能希望让列表项自行发出网络请求。我会将函数移到 ListItem 中。您需要设置一些状态来保存此值,并可能进行一些条件渲染。然后你需要在挂载组件时调用这个函数。我假设您正在使用功能组件,所以 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;
};

我通过在 componentDidMount 上的另一个 promise 方法中使用该 promise 方法解决了这个问题,并将用户的最后一条消息添加为所有用户的额外字段。这样我就可以让所有用户信息处于一种状态以填充 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
    />
  );