We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[BUG] set_props called multiple times only keep the last props.
For regular callbacks, when multiple call of `set_props` to the same component id, only the last call is saved.

Example:
```
from dash import Dash, Input, html, set_props

app = Dash()

app.layout = [
    html.Button("start", id="start"),
    html.Div("initial", id="output"),
]

@app.callback(
    Input("start", "n_clicks"),
)
def on_click(_):
    set_props("output", {"children": "changed"})
    set_props("output", {"style": {"background": "red"}})

if __name__ == "__main__":
    app.run(debug=True)

```

Clicking on the start button only set the background red, the text stays at "initial". The props should be merged and both updated.



--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `dash/long_callback/_proxy_set_props.py`
Content:
```
1 class ProxySetProps(dict):
2     """
3     Defer dictionary item setter to run a custom function on change.
4     Used by background callback manager to save the `set_props` data.
5     """
6 
7     def __init__(self, on_change):
8         super().__init__()
9         self.on_change = on_change
10 
11     def __setitem__(self, key, value):
12         self.on_change(key, value)
13
```

Path: `dash/_callback_context.py`
Content:
```
1 import functools
2 import warnings
3 import json
4 import contextvars
5 import typing
6 
7 import flask
8 
9 from . import exceptions
10 from ._utils import AttributeDict, stringify_id
11 
12 
13 context_value = contextvars.ContextVar("callback_context")
14 context_value.set({})
15 
16 
17 def has_context(func):
18     @functools.wraps(func)
19     def assert_context(*args, **kwargs):
20         if not context_value.get():
21             raise exceptions.MissingCallbackContextException(
22                 f"dash.callback_context.{getattr(func, '__name__')} is only available from a callback!"
23             )
24         return func(*args, **kwargs)
25 
26     return assert_context
27 
28 
29 def _get_context_value():
30     return context_value.get()
31 
32 
33 class FalsyList(list):
34     def __bool__(self):
35         # for Python 3
36         return False
37 
38     def __nonzero__(self):
39         # for Python 2
40         return False
41 
42 
43 falsy_triggered = FalsyList([{"prop_id": ".", "value": None}])
44 
45 
46 # pylint: disable=no-init
47 class CallbackContext:
48     @property
49     @has_context
50     def inputs(self):
51         return getattr(_get_context_value(), "input_values", {})
52 
53     @property
54     @has_context
55     def states(self):
56         return getattr(_get_context_value(), "state_values", {})
57 
58     @property
59     @has_context
60     def triggered(self):
61         """
62         Returns a list of all the Input props that changed and caused the callback to execute. It is empty when the
63         callback is called on initial load, unless an Input prop got its value from another initial callback.
64         Callbacks triggered by user actions typically have one item in triggered, unless the same action changes
65         two props at once or the callback has several Input props that are all modified by another callback based on
66         a single user action.
67 
68         Example:  To get the id of the component that triggered the callback:
69         `component_id = ctx.triggered[0]['prop_id'].split('.')[0]`
70 
71         Example:  To detect initial call, empty triggered is not really empty, it's falsy so that you can use:
72         `if ctx.triggered:`
73         """
74         # For backward compatibility: previously `triggered` always had a
75         # value - to avoid breaking existing apps, add a dummy item but
76         # make the list still look falsy. So `if ctx.triggered` will make it
77         # look empty, but you can still do `triggered[0]["prop_id"].split(".")`
78         return getattr(_get_context_value(), "triggered_inputs", []) or falsy_triggered
79 
80     @property
81     @has_context
82     def triggered_prop_ids(self):
83         """
84         Returns a dictionary of all the Input props that changed and caused the callback to execute. It is empty when
85         the callback is called on initial load, unless an Input prop got its value from another initial callback.
86         Callbacks triggered by user actions typically have one item in triggered, unless the same action changes
87         two props at once or the callback has several Input props that are all modified by another callback based
88         on a single user action.
89 
90         triggered_prop_ids (dict):
91         - keys (str) : the triggered "prop_id" composed of "component_id.component_property"
92         - values (str or dict): the id of the component that triggered the callback. Will be the dict id for pattern matching callbacks
93 
94         Example - regular callback
95         {"btn-1.n_clicks": "btn-1"}
96 
97         Example - pattern matching callbacks:
98         {'{"index":0,"type":"filter-dropdown"}.value': {"index":0,"type":"filter-dropdown"}}
99 
100         Example usage:
101         `if "btn-1.n_clicks" in ctx.triggered_prop_ids:
102             do_something()`
103         """
104         triggered = getattr(_get_context_value(), "triggered_inputs", [])
105         ids = AttributeDict({})
106         for item in triggered:
107             component_id, _, _ = item["prop_id"].rpartition(".")
108             ids[item["prop_id"]] = component_id
109             if component_id.startswith("{"):
110                 ids[item["prop_id"]] = AttributeDict(json.loads(component_id))
111         return ids
112 
113     @property
114     @has_context
115     def triggered_id(self):
116         """
117         Returns the component id (str or dict) of the Input component that triggered the callback.
118 
119         Note - use `triggered_prop_ids` if you need both the component id and the prop that triggered the callback or if
120         multiple Inputs triggered the callback.
121 
122         Example usage:
123         `if "btn-1" == ctx.triggered_id:
124             do_something()`
125 
126         """
127         component_id = None
128         if self.triggered:
129             prop_id = self.triggered_prop_ids.first()
130             component_id = self.triggered_prop_ids[prop_id]
131         return component_id
132 
133     @property
134     @has_context
135     def args_grouping(self):
136         """
137         args_grouping is a dict of the inputs used with flexible callback signatures. The keys are the variable names
138         and the values are dictionaries containing:
139         - “id”: (string or dict) the component id. If it’s a pattern matching id, it will be a dict.
140         - “id_str”: (str) for pattern matching ids, it’s the stringified dict id with no white spaces.
141         - “property”: (str) The component property used in the callback.
142         - “value”: the value of the component property at the time the callback was fired.
143         - “triggered”: (bool)Whether this input triggered the callback.
144 
145         Example usage:
146         @app.callback(
147             Output("container", "children"),
148             inputs=dict(btn1=Input("btn-1", "n_clicks"), btn2=Input("btn-2", "n_clicks")),
149         )
150         def display(btn1, btn2):
151             c = ctx.args_grouping
152             if c.btn1.triggered:
153                 return f"Button 1 clicked {btn1} times"
154             elif c.btn2.triggered:
155                 return f"Button 2 clicked {btn2} times"
156             else:
157                return "No clicks yet"
158 
159         """
160         return getattr(_get_context_value(), "args_grouping", [])
161 
162     @property
163     @has_context
164     def outputs_grouping(self):
165         return getattr(_get_context_value(), "outputs_grouping", [])
166 
167     @property
168     @has_context
169     def outputs_list(self):
170         if self.using_outputs_grouping:
171             warnings.warn(
172                 "outputs_list is deprecated, use outputs_grouping instead",
173                 DeprecationWarning,
174             )
175 
176         return getattr(_get_context_value(), "outputs_list", [])
177 
178     @property
179     @has_context
180     def inputs_list(self):
181         if self.using_args_grouping:
182             warnings.warn(
183                 "inputs_list is deprecated, use args_grouping instead",
184                 DeprecationWarning,
185             )
186 
187         return getattr(_get_context_value(), "inputs_list", [])
188 
189     @property
190     @has_context
191     def states_list(self):
192         if self.using_args_grouping:
193             warnings.warn(
194                 "states_list is deprecated, use args_grouping instead",
195                 DeprecationWarning,
196             )
197         return getattr(_get_context_value(), "states_list", [])
198 
199     @property
200     @has_context
201     def response(self):
202         return getattr(_get_context_value(), "dash_response")
203 
204     @staticmethod
205     @has_context
206     def record_timing(name, duration=None, description=None):
207         """Records timing information for a server resource.
208 
209         :param name: The name of the resource.
210         :type name: string
211 
212         :param duration: The time in seconds to report. Internally, this
213             is rounded to the nearest millisecond.
214         :type duration: float or None
215 
216         :param description: A description of the resource.
217         :type description: string or None
218         """
219         timing_information = getattr(flask.g, "timing_information", {})
220 
221         if name in timing_information:
222             raise KeyError(f'Duplicate resource name "{name}" found.')
223 
224         timing_information[name] = {"dur": round(duration * 1000), "desc": description}
225 
226         setattr(flask.g, "timing_information", timing_information)
227 
228     @property
229     @has_context
230     def using_args_grouping(self):
231         """
232         Return True if this callback is using dictionary or nested groupings for
233         Input/State dependencies, or if Input and State dependencies are interleaved
234         """
235         return getattr(_get_context_value(), "using_args_grouping", [])
236 
237     @property
238     @has_context
239     def using_outputs_grouping(self):
240         """
241         Return True if this callback is using dictionary or nested groupings for
242         Output dependencies.
243         """
244         return getattr(_get_context_value(), "using_outputs_grouping", [])
245 
246     @property
247     @has_context
248     def timing_information(self):
249         return getattr(flask.g, "timing_information", {})
250 
251     @has_context
252     def set_props(self, component_id: typing.Union[str, dict], props: dict):
253         ctx_value = _get_context_value()
254         _id = stringify_id(component_id)
255         ctx_value.updated_props[_id] = props
256 
257 
258 callback_context = CallbackContext()
259 
260 
261 def set_props(component_id: typing.Union[str, dict], props: dict):
262     """
263     Set the props for a component not included in the callback outputs.
264     """
265     callback_context.set_props(component_id, props)
266
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/dash/_callback_context.py b/dash/_callback_context.py
--- a/dash/_callback_context.py
+++ b/dash/_callback_context.py
@@ -252,7 +252,11 @@
     def set_props(self, component_id: typing.Union[str, dict], props: dict):
         ctx_value = _get_context_value()
         _id = stringify_id(component_id)
-        ctx_value.updated_props[_id] = props
+        existing = ctx_value.updated_props.get(_id)
+        if existing is not None:
+            ctx_value.updated_props[_id] = {**existing, **props}
+        else:
+            ctx_value.updated_props[_id] = props
 
 
 callback_context = CallbackContext()
diff --git a/dash/long_callback/_proxy_set_props.py b/dash/long_callback/_proxy_set_props.py
--- a/dash/long_callback/_proxy_set_props.py
+++ b/dash/long_callback/_proxy_set_props.py
@@ -7,6 +7,12 @@
     def __init__(self, on_change):
         super().__init__()
         self.on_change = on_change
+        self._data = {}
 
     def __setitem__(self, key, value):
         self.on_change(key, value)
+        self._data.setdefault(key, {})
+        self._data[key] = {**self._data[key], **value}
+
+    def get(self, key):
+        return self._data.get(key)

{"golden_diff": "diff --git a/dash/_callback_context.py b/dash/_callback_context.py\n--- a/dash/_callback_context.py\n+++ b/dash/_callback_context.py\n@@ -252,7 +252,11 @@\n     def set_props(self, component_id: typing.Union[str, dict], props: dict):\n         ctx_value = _get_context_value()\n         _id = stringify_id(component_id)\n-        ctx_value.updated_props[_id] = props\n+        existing = ctx_value.updated_props.get(_id)\n+        if existing is not None:\n+            ctx_value.updated_props[_id] = {**existing, **props}\n+        else:\n+            ctx_value.updated_props[_id] = props\n \n \n callback_context = CallbackContext()\ndiff --git a/dash/long_callback/_proxy_set_props.py b/dash/long_callback/_proxy_set_props.py\n--- a/dash/long_callback/_proxy_set_props.py\n+++ b/dash/long_callback/_proxy_set_props.py\n@@ -7,6 +7,12 @@\n     def __init__(self, on_change):\n         super().__init__()\n         self.on_change = on_change\n+        self._data = {}\n \n     def __setitem__(self, key, value):\n         self.on_change(key, value)\n+        self._data.setdefault(key, {})\n+        self._data[key] = {**self._data[key], **value}\n+\n+    def get(self, key):\n+        return self._data.get(key)\n", "issue": "[BUG] set_props called multiple times only keep the last props.\nFor regular callbacks, when multiple call of `set_props` to the same component id, only the last call is saved.\r\n\r\nExample:\r\n```\r\nfrom dash import Dash, Input, html, set_props\r\n\r\napp = Dash()\r\n\r\napp.layout = [\r\n    html.Button(\"start\", id=\"start\"),\r\n    html.Div(\"initial\", id=\"output\"),\r\n]\r\n\r\n@app.callback(\r\n    Input(\"start\", \"n_clicks\"),\r\n)\r\ndef on_click(_):\r\n    set_props(\"output\", {\"children\": \"changed\"})\r\n    set_props(\"output\", {\"style\": {\"background\": \"red\"}})\r\n\r\nif __name__ == \"__main__\":\r\n    app.run(debug=True)\r\n\r\n```\r\n\r\nClicking on the start button only set the background red, the text stays at \"initial\". The props should be merged and both updated.\r\n\r\n\n", "before_files": [{"content": "class ProxySetProps(dict):\n    \"\"\"\n    Defer dictionary item setter to run a custom function on change.\n    Used by background callback manager to save the `set_props` data.\n    \"\"\"\n\n    def __init__(self, on_change):\n        super().__init__()\n        self.on_change = on_change\n\n    def __setitem__(self, key, value):\n        self.on_change(key, value)\n", "path": "dash/long_callback/_proxy_set_props.py"}, {"content": "import functools\nimport warnings\nimport json\nimport contextvars\nimport typing\n\nimport flask\n\nfrom . import exceptions\nfrom ._utils import AttributeDict, stringify_id\n\n\ncontext_value = contextvars.ContextVar(\"callback_context\")\ncontext_value.set({})\n\n\ndef has_context(func):\n    @functools.wraps(func)\n    def assert_context(*args, **kwargs):\n        if not context_value.get():\n            raise exceptions.MissingCallbackContextException(\n                f\"dash.callback_context.{getattr(func, '__name__')} is only available from a callback!\"\n            )\n        return func(*args, **kwargs)\n\n    return assert_context\n\n\ndef _get_context_value():\n    return context_value.get()\n\n\nclass FalsyList(list):\n    def __bool__(self):\n        # for Python 3\n        return False\n\n    def __nonzero__(self):\n        # for Python 2\n        return False\n\n\nfalsy_triggered = FalsyList([{\"prop_id\": \".\", \"value\": None}])\n\n\n# pylint: disable=no-init\nclass CallbackContext:\n    @property\n    @has_context\n    def inputs(self):\n        return getattr(_get_context_value(), \"input_values\", {})\n\n    @property\n    @has_context\n    def states(self):\n        return getattr(_get_context_value(), \"state_values\", {})\n\n    @property\n    @has_context\n    def triggered(self):\n        \"\"\"\n        Returns a list of all the Input props that changed and caused the callback to execute. It is empty when the\n        callback is called on initial load, unless an Input prop got its value from another initial callback.\n        Callbacks triggered by user actions typically have one item in triggered, unless the same action changes\n        two props at once or the callback has several Input props that are all modified by another callback based on\n        a single user action.\n\n        Example:  To get the id of the component that triggered the callback:\n        `component_id = ctx.triggered[0]['prop_id'].split('.')[0]`\n\n        Example:  To detect initial call, empty triggered is not really empty, it's falsy so that you can use:\n        `if ctx.triggered:`\n        \"\"\"\n        # For backward compatibility: previously `triggered` always had a\n        # value - to avoid breaking existing apps, add a dummy item but\n        # make the list still look falsy. So `if ctx.triggered` will make it\n        # look empty, but you can still do `triggered[0][\"prop_id\"].split(\".\")`\n        return getattr(_get_context_value(), \"triggered_inputs\", []) or falsy_triggered\n\n    @property\n    @has_context\n    def triggered_prop_ids(self):\n        \"\"\"\n        Returns a dictionary of all the Input props that changed and caused the callback to execute. It is empty when\n        the callback is called on initial load, unless an Input prop got its value from another initial callback.\n        Callbacks triggered by user actions typically have one item in triggered, unless the same action changes\n        two props at once or the callback has several Input props that are all modified by another callback based\n        on a single user action.\n\n        triggered_prop_ids (dict):\n        - keys (str) : the triggered \"prop_id\" composed of \"component_id.component_property\"\n        - values (str or dict): the id of the component that triggered the callback. Will be the dict id for pattern matching callbacks\n\n        Example - regular callback\n        {\"btn-1.n_clicks\": \"btn-1\"}\n\n        Example - pattern matching callbacks:\n        {'{\"index\":0,\"type\":\"filter-dropdown\"}.value': {\"index\":0,\"type\":\"filter-dropdown\"}}\n\n        Example usage:\n        `if \"btn-1.n_clicks\" in ctx.triggered_prop_ids:\n            do_something()`\n        \"\"\"\n        triggered = getattr(_get_context_value(), \"triggered_inputs\", [])\n        ids = AttributeDict({})\n        for item in triggered:\n            component_id, _, _ = item[\"prop_id\"].rpartition(\".\")\n            ids[item[\"prop_id\"]] = component_id\n            if component_id.startswith(\"{\"):\n                ids[item[\"prop_id\"]] = AttributeDict(json.loads(component_id))\n        return ids\n\n    @property\n    @has_context\n    def triggered_id(self):\n        \"\"\"\n        Returns the component id (str or dict) of the Input component that triggered the callback.\n\n        Note - use `triggered_prop_ids` if you need both the component id and the prop that triggered the callback or if\n        multiple Inputs triggered the callback.\n\n        Example usage:\n        `if \"btn-1\" == ctx.triggered_id:\n            do_something()`\n\n        \"\"\"\n        component_id = None\n        if self.triggered:\n            prop_id = self.triggered_prop_ids.first()\n            component_id = self.triggered_prop_ids[prop_id]\n        return component_id\n\n    @property\n    @has_context\n    def args_grouping(self):\n        \"\"\"\n        args_grouping is a dict of the inputs used with flexible callback signatures. The keys are the variable names\n        and the values are dictionaries containing:\n        - \u201cid\u201d: (string or dict) the component id. If it\u2019s a pattern matching id, it will be a dict.\n        - \u201cid_str\u201d: (str) for pattern matching ids, it\u2019s the stringified dict id with no white spaces.\n        - \u201cproperty\u201d: (str) The component property used in the callback.\n        - \u201cvalue\u201d: the value of the component property at the time the callback was fired.\n        - \u201ctriggered\u201d: (bool)Whether this input triggered the callback.\n\n        Example usage:\n        @app.callback(\n            Output(\"container\", \"children\"),\n            inputs=dict(btn1=Input(\"btn-1\", \"n_clicks\"), btn2=Input(\"btn-2\", \"n_clicks\")),\n        )\n        def display(btn1, btn2):\n            c = ctx.args_grouping\n            if c.btn1.triggered:\n                return f\"Button 1 clicked {btn1} times\"\n            elif c.btn2.triggered:\n                return f\"Button 2 clicked {btn2} times\"\n            else:\n               return \"No clicks yet\"\n\n        \"\"\"\n        return getattr(_get_context_value(), \"args_grouping\", [])\n\n    @property\n    @has_context\n    def outputs_grouping(self):\n        return getattr(_get_context_value(), \"outputs_grouping\", [])\n\n    @property\n    @has_context\n    def outputs_list(self):\n        if self.using_outputs_grouping:\n            warnings.warn(\n                \"outputs_list is deprecated, use outputs_grouping instead\",\n                DeprecationWarning,\n            )\n\n        return getattr(_get_context_value(), \"outputs_list\", [])\n\n    @property\n    @has_context\n    def inputs_list(self):\n        if self.using_args_grouping:\n            warnings.warn(\n                \"inputs_list is deprecated, use args_grouping instead\",\n                DeprecationWarning,\n            )\n\n        return getattr(_get_context_value(), \"inputs_list\", [])\n\n    @property\n    @has_context\n    def states_list(self):\n        if self.using_args_grouping:\n            warnings.warn(\n                \"states_list is deprecated, use args_grouping instead\",\n                DeprecationWarning,\n            )\n        return getattr(_get_context_value(), \"states_list\", [])\n\n    @property\n    @has_context\n    def response(self):\n        return getattr(_get_context_value(), \"dash_response\")\n\n    @staticmethod\n    @has_context\n    def record_timing(name, duration=None, description=None):\n        \"\"\"Records timing information for a server resource.\n\n        :param name: The name of the resource.\n        :type name: string\n\n        :param duration: The time in seconds to report. Internally, this\n            is rounded to the nearest millisecond.\n        :type duration: float or None\n\n        :param description: A description of the resource.\n        :type description: string or None\n        \"\"\"\n        timing_information = getattr(flask.g, \"timing_information\", {})\n\n        if name in timing_information:\n            raise KeyError(f'Duplicate resource name \"{name}\" found.')\n\n        timing_information[name] = {\"dur\": round(duration * 1000), \"desc\": description}\n\n        setattr(flask.g, \"timing_information\", timing_information)\n\n    @property\n    @has_context\n    def using_args_grouping(self):\n        \"\"\"\n        Return True if this callback is using dictionary or nested groupings for\n        Input/State dependencies, or if Input and State dependencies are interleaved\n        \"\"\"\n        return getattr(_get_context_value(), \"using_args_grouping\", [])\n\n    @property\n    @has_context\n    def using_outputs_grouping(self):\n        \"\"\"\n        Return True if this callback is using dictionary or nested groupings for\n        Output dependencies.\n        \"\"\"\n        return getattr(_get_context_value(), \"using_outputs_grouping\", [])\n\n    @property\n    @has_context\n    def timing_information(self):\n        return getattr(flask.g, \"timing_information\", {})\n\n    @has_context\n    def set_props(self, component_id: typing.Union[str, dict], props: dict):\n        ctx_value = _get_context_value()\n        _id = stringify_id(component_id)\n        ctx_value.updated_props[_id] = props\n\n\ncallback_context = CallbackContext()\n\n\ndef set_props(component_id: typing.Union[str, dict], props: dict):\n    \"\"\"\n    Set the props for a component not included in the callback outputs.\n    \"\"\"\n    callback_context.set_props(component_id, props)\n", "path": "dash/_callback_context.py"}], "after_files": [{"content": "class ProxySetProps(dict):\n    \"\"\"\n    Defer dictionary item setter to run a custom function on change.\n    Used by background callback manager to save the `set_props` data.\n    \"\"\"\n\n    def __init__(self, on_change):\n        super().__init__()\n        self.on_change = on_change\n        self._data = {}\n\n    def __setitem__(self, key, value):\n        self.on_change(key, value)\n        self._data.setdefault(key, {})\n        self._data[key] = {**self._data[key], **value}\n\n    def get(self, key):\n        return self._data.get(key)\n", "path": "dash/long_callback/_proxy_set_props.py"}, {"content": "import functools\nimport warnings\nimport json\nimport contextvars\nimport typing\n\nimport flask\n\nfrom . import exceptions\nfrom ._utils import AttributeDict, stringify_id\n\n\ncontext_value = contextvars.ContextVar(\"callback_context\")\ncontext_value.set({})\n\n\ndef has_context(func):\n    @functools.wraps(func)\n    def assert_context(*args, **kwargs):\n        if not context_value.get():\n            raise exceptions.MissingCallbackContextException(\n                f\"dash.callback_context.{getattr(func, '__name__')} is only available from a callback!\"\n            )\n        return func(*args, **kwargs)\n\n    return assert_context\n\n\ndef _get_context_value():\n    return context_value.get()\n\n\nclass FalsyList(list):\n    def __bool__(self):\n        # for Python 3\n        return False\n\n    def __nonzero__(self):\n        # for Python 2\n        return False\n\n\nfalsy_triggered = FalsyList([{\"prop_id\": \".\", \"value\": None}])\n\n\n# pylint: disable=no-init\nclass CallbackContext:\n    @property\n    @has_context\n    def inputs(self):\n        return getattr(_get_context_value(), \"input_values\", {})\n\n    @property\n    @has_context\n    def states(self):\n        return getattr(_get_context_value(), \"state_values\", {})\n\n    @property\n    @has_context\n    def triggered(self):\n        \"\"\"\n        Returns a list of all the Input props that changed and caused the callback to execute. It is empty when the\n        callback is called on initial load, unless an Input prop got its value from another initial callback.\n        Callbacks triggered by user actions typically have one item in triggered, unless the same action changes\n        two props at once or the callback has several Input props that are all modified by another callback based on\n        a single user action.\n\n        Example:  To get the id of the component that triggered the callback:\n        `component_id = ctx.triggered[0]['prop_id'].split('.')[0]`\n\n        Example:  To detect initial call, empty triggered is not really empty, it's falsy so that you can use:\n        `if ctx.triggered:`\n        \"\"\"\n        # For backward compatibility: previously `triggered` always had a\n        # value - to avoid breaking existing apps, add a dummy item but\n        # make the list still look falsy. So `if ctx.triggered` will make it\n        # look empty, but you can still do `triggered[0][\"prop_id\"].split(\".\")`\n        return getattr(_get_context_value(), \"triggered_inputs\", []) or falsy_triggered\n\n    @property\n    @has_context\n    def triggered_prop_ids(self):\n        \"\"\"\n        Returns a dictionary of all the Input props that changed and caused the callback to execute. It is empty when\n        the callback is called on initial load, unless an Input prop got its value from another initial callback.\n        Callbacks triggered by user actions typically have one item in triggered, unless the same action changes\n        two props at once or the callback has several Input props that are all modified by another callback based\n        on a single user action.\n\n        triggered_prop_ids (dict):\n        - keys (str) : the triggered \"prop_id\" composed of \"component_id.component_property\"\n        - values (str or dict): the id of the component that triggered the callback. Will be the dict id for pattern matching callbacks\n\n        Example - regular callback\n        {\"btn-1.n_clicks\": \"btn-1\"}\n\n        Example - pattern matching callbacks:\n        {'{\"index\":0,\"type\":\"filter-dropdown\"}.value': {\"index\":0,\"type\":\"filter-dropdown\"}}\n\n        Example usage:\n        `if \"btn-1.n_clicks\" in ctx.triggered_prop_ids:\n            do_something()`\n        \"\"\"\n        triggered = getattr(_get_context_value(), \"triggered_inputs\", [])\n        ids = AttributeDict({})\n        for item in triggered:\n            component_id, _, _ = item[\"prop_id\"].rpartition(\".\")\n            ids[item[\"prop_id\"]] = component_id\n            if component_id.startswith(\"{\"):\n                ids[item[\"prop_id\"]] = AttributeDict(json.loads(component_id))\n        return ids\n\n    @property\n    @has_context\n    def triggered_id(self):\n        \"\"\"\n        Returns the component id (str or dict) of the Input component that triggered the callback.\n\n        Note - use `triggered_prop_ids` if you need both the component id and the prop that triggered the callback or if\n        multiple Inputs triggered the callback.\n\n        Example usage:\n        `if \"btn-1\" == ctx.triggered_id:\n            do_something()`\n\n        \"\"\"\n        component_id = None\n        if self.triggered:\n            prop_id = self.triggered_prop_ids.first()\n            component_id = self.triggered_prop_ids[prop_id]\n        return component_id\n\n    @property\n    @has_context\n    def args_grouping(self):\n        \"\"\"\n        args_grouping is a dict of the inputs used with flexible callback signatures. The keys are the variable names\n        and the values are dictionaries containing:\n        - \u201cid\u201d: (string or dict) the component id. If it\u2019s a pattern matching id, it will be a dict.\n        - \u201cid_str\u201d: (str) for pattern matching ids, it\u2019s the stringified dict id with no white spaces.\n        - \u201cproperty\u201d: (str) The component property used in the callback.\n        - \u201cvalue\u201d: the value of the component property at the time the callback was fired.\n        - \u201ctriggered\u201d: (bool)Whether this input triggered the callback.\n\n        Example usage:\n        @app.callback(\n            Output(\"container\", \"children\"),\n            inputs=dict(btn1=Input(\"btn-1\", \"n_clicks\"), btn2=Input(\"btn-2\", \"n_clicks\")),\n        )\n        def display(btn1, btn2):\n            c = ctx.args_grouping\n            if c.btn1.triggered:\n                return f\"Button 1 clicked {btn1} times\"\n            elif c.btn2.triggered:\n                return f\"Button 2 clicked {btn2} times\"\n            else:\n               return \"No clicks yet\"\n\n        \"\"\"\n        return getattr(_get_context_value(), \"args_grouping\", [])\n\n    @property\n    @has_context\n    def outputs_grouping(self):\n        return getattr(_get_context_value(), \"outputs_grouping\", [])\n\n    @property\n    @has_context\n    def outputs_list(self):\n        if self.using_outputs_grouping:\n            warnings.warn(\n                \"outputs_list is deprecated, use outputs_grouping instead\",\n                DeprecationWarning,\n            )\n\n        return getattr(_get_context_value(), \"outputs_list\", [])\n\n    @property\n    @has_context\n    def inputs_list(self):\n        if self.using_args_grouping:\n            warnings.warn(\n                \"inputs_list is deprecated, use args_grouping instead\",\n                DeprecationWarning,\n            )\n\n        return getattr(_get_context_value(), \"inputs_list\", [])\n\n    @property\n    @has_context\n    def states_list(self):\n        if self.using_args_grouping:\n            warnings.warn(\n                \"states_list is deprecated, use args_grouping instead\",\n                DeprecationWarning,\n            )\n        return getattr(_get_context_value(), \"states_list\", [])\n\n    @property\n    @has_context\n    def response(self):\n        return getattr(_get_context_value(), \"dash_response\")\n\n    @staticmethod\n    @has_context\n    def record_timing(name, duration=None, description=None):\n        \"\"\"Records timing information for a server resource.\n\n        :param name: The name of the resource.\n        :type name: string\n\n        :param duration: The time in seconds to report. Internally, this\n            is rounded to the nearest millisecond.\n        :type duration: float or None\n\n        :param description: A description of the resource.\n        :type description: string or None\n        \"\"\"\n        timing_information = getattr(flask.g, \"timing_information\", {})\n\n        if name in timing_information:\n            raise KeyError(f'Duplicate resource name \"{name}\" found.')\n\n        timing_information[name] = {\"dur\": round(duration * 1000), \"desc\": description}\n\n        setattr(flask.g, \"timing_information\", timing_information)\n\n    @property\n    @has_context\n    def using_args_grouping(self):\n        \"\"\"\n        Return True if this callback is using dictionary or nested groupings for\n        Input/State dependencies, or if Input and State dependencies are interleaved\n        \"\"\"\n        return getattr(_get_context_value(), \"using_args_grouping\", [])\n\n    @property\n    @has_context\n    def using_outputs_grouping(self):\n        \"\"\"\n        Return True if this callback is using dictionary or nested groupings for\n        Output dependencies.\n        \"\"\"\n        return getattr(_get_context_value(), \"using_outputs_grouping\", [])\n\n    @property\n    @has_context\n    def timing_information(self):\n        return getattr(flask.g, \"timing_information\", {})\n\n    @has_context\n    def set_props(self, component_id: typing.Union[str, dict], props: dict):\n        ctx_value = _get_context_value()\n        _id = stringify_id(component_id)\n        existing = ctx_value.updated_props.get(_id)\n        if existing is not None:\n            ctx_value.updated_props[_id] = {**existing, **props}\n        else:\n            ctx_value.updated_props[_id] = props\n\n\ncallback_context = CallbackContext()\n\n\ndef set_props(component_id: typing.Union[str, dict], props: dict):\n    \"\"\"\n    Set the props for a component not included in the callback outputs.\n    \"\"\"\n    callback_context.set_props(component_id, props)\n", "path": "dash/_callback_context.py"}]}