# React Context API in Python

**URL:** <https://discuss.python.org/t/react-context-api-in-python/5684>\
**Category:** Ideas\
**Created:** [November 7, 2020, 11:37am UTC](https://discuss.python.org/t/react-context-api-in-python/5684 "2020-11-07T11:37:32Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![mdamien](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/mdamien/32/2838_2.png) [@mdamien](https://discuss.python.org/u/mdamien)\
**Post date:** [November 7, 2020, 11:37am UTC](https://discuss.python.org/t/react-context-api-in-python/5684/1 "2020-11-07T11:37:32Z")

</div>

When you are deep down in a function inside a function inside another function and you need something from the first function, you need to pass it all the way down to the last function. But with the concept of React Context, you create a variable that you can retrieve at any level without the need to pass it down. Better than a global variable, more flexible than a class or using nonlocal.

Here’s a demo of what it looks like in Python. I think the idea is so good it should be built-in in a next version of Python and I will try to propose a PEP if people like this.

```auto
### LIBRARY ###

from contextlib import contextmanager

CURRENT_CONTEXT = {}
@contextmanager
def use_context(**kwargs):
    global CURRENT_CONTEXT
    try:
        for key, value in kwargs.items():
            CURRENT_CONTEXT[key] = value
        yield
    finally:
        for key, value in kwargs.items():
            del CURRENT_CONTEXT[key]

def get_context(key):
    global CURRENT_CONTEXT
    return CURRENT_CONTEXT[key]

####################################

### USAGE ###

def do_something_with_current_user(user):
    print(user)

def another_function():
    user = get_context('user')
    do_something_with_current_user(user)

def function_between():
    another_function()

def first_function():
    user = "vicky"
    with use_context(user=user):
        function_between()

```

EDIT: Of course this version doesn’t work with multiple threads

---

<div class="post-metadata">

**Author:** ![encukou](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/encukou/32/2461_2.png) [@encukou](https://discuss.python.org/u/encukou)\
**Post date:** [November 7, 2020, 12:32pm UTC](https://discuss.python.org/t/react-context-api-in-python/5684/2 "2020-11-07T12:32:12Z")

</div>

As it happens, Yuri already wrote [a PEP](https://www.python.org/dev/peps/pep-0567/) for something very similar: [contextvars](https://docs.python.org/3/library/contextvars.html).

---

<div class="post-metadata">

**Author:** ![mdamien](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/mdamien/32/2838_2.png) [@mdamien](https://discuss.python.org/u/mdamien)\
**Post date:** [November 7, 2020, 1:12pm UTC](https://discuss.python.org/t/react-context-api-in-python/5684/3 "2020-11-07T13:12:05Z")

</div>

Thanks, it doesn’t look as clean, maybe I don’t know how to use it well, here’s my example transformed to look use contextvars:

```
import contextvars

user_var = contextvars.ContextVar('user')

def do_something_with_current_user(user):
    print(user)

def another_function():
    user = user_var.get()
    do_something_with_current_user(user)

def function_between():
    another_function()

def first_function():
    user = "vicky"
    token = user_var.set(user)
    function_between()
    user_var.reset(token)
```

---

<div class="post-metadata">

**Author:** ![oscarbenjamin](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/oscarbenjamin/32/1209_2.png) [@oscarbenjamin](https://discuss.python.org/u/oscarbenjamin)\
**Post date:** [November 7, 2020, 3:38pm UTC](https://discuss.python.org/t/react-context-api-in-python/5684/4 "2020-11-07T15:38:08Z")

</div>

> When you are deep down in a function inside a function inside another function and you need something from the first function, you need to pass it all the way down to the last function. But with the concept of React Context, you create a variable that you can retrieve at any level without the need to pass it down. Better than a global variable, more flexible than a class or using nonlocal.

> Here’s a demo of what it looks like in Python. I think the idea is so good it should be built-in in a next version of Python and I will try to propose a PEP if people like this.

```auto
### LIBRARY ###

from contextlib import contextmanager

CURRENT_CONTEXT = {}
@contextmanager
def use_context(**kwargs):
    global CURRENT_CONTEXT

```

You say that this is “better than a global variable” but in the demonstration it is just a function wrapping a global variable. The example as shown would suffer all the same problems as a global variable such as non-reentrancy.

If the context manager is used over the top of itself then it clobbers everything e.g.:

```auto
def func1():
    with use_context(user='foo'):
        func2()
        # func2 has wiped the user key so this will raise:
        func3()

def func2():
    with use_context(user='bar'):
        func4()

def func4():
    return

def func3():
    user = get_context('user')

```

---

<div class="post-metadata">

**Author:** ![mdamien](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/mdamien/32/2838_2.png) [@mdamien](https://discuss.python.org/u/mdamien)\
**Post date:** [November 7, 2020, 5:46pm UTC](https://discuss.python.org/t/react-context-api-in-python/5684/5 "2020-11-07T17:46:51Z")

</div>

Here it’s a toy implementation, it’s easy to fix the double calling of use\_context in the implementation.

I agree, it’s not yet ready for a PEP 🙂, just throwing the idea around to see if other people like it.

---

<div class="post-metadata">

**Author:** ![EpicWink](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/epicwink/32/17968_2.png) [@EpicWink](https://discuss.python.org/u/EpicWink)\
**Post date:** [November 7, 2020, 11:01pm UTC](https://discuss.python.org/t/react-context-api-in-python/5684/6 "2020-11-07T23:01:26Z")

</div>

It certainly looks convenient, but newcomers to code which would use this feature would have a hard time find where the context values are set.

---

<div class="post-metadata">

**Author:** ![apagiaro](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/apagiaro/32/10490_2.png) [@apagiaro](https://discuss.python.org/u/apagiaro)\
**Post date:** [January 6, 2023, 12:30pm UTC](https://discuss.python.org/t/react-context-api-in-python/5684/7 "2023-01-06T12:30:08Z")

</div>

I coded a library inspired by this post that works in several scenarios.  
It also exposes a debug mode to understand where the context has been defined in the upper functions.

You can check the implementation here: [GitHub - alessandro308/react\_context: An API to pass data down in the sub-function inspired by React Context](https://github.com/alessandro308/react_context)
