如何使用recompose的toClass HOC将ref添加到功能组件?

时间:2017-10-04 19:28:08

标签: reactjs react-native ref recompose

我正在尝试在React Native中添加一个函数组件,以便在FlatList组件上使用scrollToEnd。

我想对此进行重构,并且正如他们的文档所述,toClass()应该能够处理这个问题。但是,没有给出任何例子。

目前,这是我失败的实施。有人能告诉我我做错了什么吗?

我非常感激!

import React from 'react';
import PropTypes from 'prop-types';
import { FlatList, View, Text } from 'react-native';
import { graphql } from 'react-apollo';
import { compose, toClass, lifecycle } from 'recompose';

import CommentItem from './CommentItem';
import { commentsQuery } from '../../queries/comments';

const CommentScreen = ({ onRef, currentUser, data: { comments, loading } }) => {
  if (loading) {
    return (
      <View>
        <Text>Loading...</Text>
      </View>
    );
  }

  return (
    <FlatList
      ref={ref => {
        this.refs.commentList = ref;
      }}
      data={comments}
      keyExtractor={item => item.id}
      renderItem={({ item }) => <CommentItem {...item} currentUser={currentUser} />}
    />
  );
};

export default compose(
  toClass,
  graphql(commentsQuery),
  lifecycle({
    componentDidMount() {
      console.log('PROPZZZ', this.commentList);
    },
  }),
)(CommentScreen);

CommentScreen.propTypes = {
  fetchComments: PropTypes.func.isRequired,
  updateId: PropTypes.number.isRequired,
  comments: PropTypes.arrayOf(Object),
  text: PropTypes.string.isRequired,
};

3 个答案:

答案 0 :(得分:1)

如果您需要使用ref,只需使用类组件而不是功能组件。但是,如果由于某些原因需要使用功能组件,则可以使用withHandlers。请参阅this SO question的答案,了解如何使用它。

答案 1 :(得分:0)

您必须从生命周期方法中的this.refs访问您的元素。

lifecycle({
  componentDidMount() {
    console.log('PROPZZZ', this.refs.commentList);
    //                          ^^^^
  }
})

你可以看到它在这里工作: https://snack.expo.io/Sy-rCBQhW

答案 2 :(得分:0)

我将粘贴一些我设法解决类似问题的代码,我知道这不完全是您的代码,但它显示了解决方案:

import React from 'react'
import { compose, withState, withHandlers, lifecycle } from 'recompose'

import Left from './Left'
import Right from './Right'
import Modals from './Modals'
import { ActionBar, Container } from './styles'

let ref = null

const enhance = compose(
  withState('position', 'setPos', 'relative'),
  withHandlers({
    isTop: ({ setPos }) => () => {
      const { top } = ref && ref.getBoundingClientRect()
      top && setPos(top <= 0 ? 'fixed' : 'relative')
    },
  }),
  lifecycle({
    componentDidMount() {
      window.addEventListener('scroll', this.props.isTop)
    },
    componentWillUnmount() {
      window.removeEventListener('scroll', this.props.isTop)
    },
  })
)

export default enhance(({ position, ...props }) => (
  <Container innerRef={el => (ref = el)}>
    <ActionBar position={position}>
      <Left {...props} />
      <Right {...props} />
      <Modals {...props} />
    </ActionBar>
  </Container>
))

正如您所看到的,这里的关键是将ref存储在变量中,并使用withState + withHandlers + lifecycle的混合使其有效,我没有最终不需要使用toClass HoC,因为只要您使用recompose中的任何其他HoC ,您就已经在下面使用了React组件类:)

希望有帮助!