Was refactoring my class component to Functional one, and faced a very difficult issue with useEffect

Viewed 70

i guess the problem, when i refactor codes from class to functional component in react, is because there is no prevProps easily allowed in useEffect. and i don't exactly know how to solve it.

first, there is variables for prop-type like this.

const propTypes = {
  items: PropTypes.array.isRequired,
  onChangePage: PropTypes.func.isRequired,
  initialPage: PropTypes.number,
  pageSize: PropTypes.number,
};
const defaultProps = {
  initialPage: 1,
  pageSize: 5,
};

and then below that i wrote a class component which works alright.

class Pagination extends React.Component {
  constructor(props) {
    super(props);
    this.state = { pager: {} };
  }
  componentDidMount() {
    if (this.props.items && this.props.items.length) {
      this.setPage(this.props.initialPage);
    }
  }
  componentDidUpdate(prevProps) {
    if (this.props.items !== prevProps.items) {
      this.setPage(this.props.initialPage);
    }
  }

and then here is the problem. I tried to change the class component to Functional one. It looks like this.

function Pagination2(props) {
const [pager, setPager] = useState({ pager: {} });
  useEffect(() => {
    if (props.items && props.items.length) {
      setPage(props.initialPage);
    }
  }, []);

  const usePrevious = (value) => {
    const ref = useRef();
    useEffect(() => {
      ref.current = value;
    });
    return ref.current;
  };
  const prevItems = usePrevious(props.items);
  useEffect(() => {
    if (props.items !== prevItems) {
      setPage(props.initialPage);
    }
    console.log(prevItems); -> it shows undefined on console
  }, []);

it totally doesn't work and i've been stuck in it for a long time. How can i solve this issue? I'm willing to hear anything here. Thanks a lot!

2 Answers

you can do it in only one useEffect

function Pagination2(props){

  function setPage(data){
    //TODO
  }

  useEffect(() => {
    if(!props.items && !props.items.length) return
    setPage(props.initialPage)
  }, [props.items])

  return "hi"
}

useEffect will only run when props.items changes

If I understood your intention correctly, you want the Pagination component to start with initialPage in it's page state variable; and reset to it whenever props.items are changed:

function Pagination2(props) {
    const { items, initialPage } = props;
  
    const [page, setPage] = useState(initialPage);
    const prevItems = useRef(items).current;

    useEffect(() => {
        if(items !== prevItems) setPage(initialPage); // Comparison

        return () => {
            prevItems = items;
        };
    }, [items]);
}
Related