I had the same problem not long ago. There are 4 solutions I found for this.
Passing t
down to every component. This one is very annoying and leads to a lot of bugs because I was forgetting to pass it down all the time.
Using the NamespacesConsumer context provided by react-i18next. This one is also really annoying and the syntax is sometimes too weird and repetitive. This can also be bad for performance because components might re-render often.
Using the withNamespaces
HOC provided by react-i18next, this is a great option, it's easy to read and doesn't pollute your code with translation syntax. It's also more efficient than the previous two options.
This one is my favorite solution, I end up using i18next directly because you have access to t()
everywhere out of the box, without additional code.
If you want to keep react-i18next, I would recommend you to use a HOC, it's way easier to debug, test and develop. But honestly, i18next is doing a better job in my own opinion. I initially use react-i18next because I thought it was the react way to go, but it is just a pain to use it, react-i18next has a lot of bugs and it's way more code to write. Using i18next is simple as this
import i18next from 'i18next';
i18next.t('parentKey.childKey');