Epoll is a readyness notification API. You tell epoll which fd's you're interested in, then you run a poll operation which blocks until at least one of the fd's you're interested in is ready. Then you separately need to do the actual IO (which is essentially just a memcpy() between kernel and user space).
In contrast io_uring is a completion notification API. You give it a buffer to read or write from/to, and it'll notify you when the IO has been completed.
Io_uring is also more flexible, and can for example be used for disk IO which epoll can't.