We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
 experimental_get_query_params  won't work before rerun 
### Checklist

- [X] I have searched the [existing issues](https://github.com/streamlit/streamlit/issues) for similar issues.
- [X] I added a very descriptive title to this issue.
- [X] I have provided sufficient information below to help reproduce this issue.

### Summary

User can not get right query_params before rerun.

### Reproducible Code Example

```Python
import streamlit as st

st.experimental_set_query_params(param=3)
st.write(st.experimental_get_query_params())
```


### Steps To Reproduce

Run script, `{"param ": 3}` will not appear at first time until rerun script after querystring in browser already changed.

### Expected Behavior

Show `{"param ": 3}`

### Current Behavior

show empty dict

### Is this a regression?

- [X] Yes, this used to work in a previous version.

### Debug info

- Streamlit version: 1.20.0
- Python version: 3.10.6
- Operating System: Linux
- Browser: Chrome
- Virtual environment: None


### Additional Information

In previous version `set_query_params` will set `ctx.query_string = parse.urlencode(query_params, doseq=True)` immediately.

But in 1.20, this line is removed while `get_query_params` still get if from `ctx.query_string` .

### Are you willing to submit a PR?

- [x] Yes, I am willing to submit a PR!

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `lib/streamlit/commands/query_params.py`
Content:
```
1 # Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022)
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #     http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 
15 import urllib.parse as parse
16 from typing import Any, Dict, List
17 
18 from streamlit import util
19 from streamlit.errors import StreamlitAPIException
20 from streamlit.proto.ForwardMsg_pb2 import ForwardMsg
21 from streamlit.runtime.metrics_util import gather_metrics
22 from streamlit.runtime.scriptrunner import get_script_run_ctx
23 
24 EMBED_QUERY_PARAM = "embed"
25 EMBED_OPTIONS_QUERY_PARAM = "embed_options"
26 EMBED_QUERY_PARAMS_KEYS = [EMBED_QUERY_PARAM, EMBED_OPTIONS_QUERY_PARAM]
27 
28 
29 @gather_metrics("experimental_get_query_params")
30 def get_query_params() -> Dict[str, List[str]]:
31     """Return the query parameters that is currently showing in the browser's URL bar.
32 
33     Returns
34     -------
35     dict
36       The current query parameters as a dict. "Query parameters" are the part of the URL that comes
37       after the first "?".
38 
39     Example
40     -------
41     Let's say the user's web browser is at
42     `http://localhost:8501/?show_map=True&selected=asia&selected=america`.
43     Then, you can get the query parameters using the following:
44 
45     >>> import streamlit as st
46     >>>
47     >>> st.experimental_get_query_params()
48     {"show_map": ["True"], "selected": ["asia", "america"]}
49 
50     Note that the values in the returned dict are *always* lists. This is
51     because we internally use Python's urllib.parse.parse_qs(), which behaves
52     this way. And this behavior makes sense when you consider that every item
53     in a query string is potentially a 1-element array.
54 
55     """
56     ctx = get_script_run_ctx()
57     if ctx is None:
58         return {}
59     # Return new query params dict, but without embed, embed_options query params
60     return util.exclude_key_query_params(
61         parse.parse_qs(ctx.query_string), keys_to_exclude=EMBED_QUERY_PARAMS_KEYS
62     )
63 
64 
65 @gather_metrics("experimental_set_query_params")
66 def set_query_params(**query_params: Any) -> None:
67     """Set the query parameters that are shown in the browser's URL bar.
68 
69     .. warning::
70         Query param `embed` cannot be set using this method.
71 
72     Parameters
73     ----------
74     **query_params : dict
75         The query parameters to set, as key-value pairs.
76 
77     Example
78     -------
79 
80     To point the user's web browser to something like
81     "http://localhost:8501/?show_map=True&selected=asia&selected=america",
82     you would do the following:
83 
84     >>> import streamlit as st
85     >>>
86     >>> st.experimental_set_query_params(
87     ...     show_map=True,
88     ...     selected=["asia", "america"],
89     ... )
90 
91     """
92     ctx = get_script_run_ctx()
93     if ctx is None:
94         return
95 
96     msg = ForwardMsg()
97     msg.page_info_changed.query_string = _ensure_no_embed_params(
98         query_params, ctx.query_string
99     )
100     ctx.enqueue(msg)
101 
102 
103 def _ensure_no_embed_params(
104     query_params: Dict[str, List[str]], query_string: str
105 ) -> str:
106     """Ensures there are no embed params set (raises StreamlitAPIException) if there is a try,
107     also makes sure old param values in query_string are preserved. Returns query_string : str."""
108     # Get query params dict without embed, embed_options params
109     query_params_without_embed = util.exclude_key_query_params(
110         query_params, keys_to_exclude=EMBED_QUERY_PARAMS_KEYS
111     )
112     if query_params != query_params_without_embed:
113         raise StreamlitAPIException(
114             "Query param embed and embed_options (case-insensitive) cannot be set using set_query_params method."
115         )
116 
117     all_current_params = parse.parse_qs(query_string)
118     current_embed_params = parse.urlencode(
119         {
120             EMBED_QUERY_PARAM: [
121                 param
122                 for param in util.extract_key_query_params(
123                     all_current_params, param_key=EMBED_QUERY_PARAM
124                 )
125             ],
126             EMBED_OPTIONS_QUERY_PARAM: [
127                 param
128                 for param in util.extract_key_query_params(
129                     all_current_params, param_key=EMBED_OPTIONS_QUERY_PARAM
130                 )
131             ],
132         },
133         doseq=True,
134     )
135     query_string = parse.urlencode(query_params, doseq=True)
136 
137     if query_string:
138         separator = "&" if current_embed_params else ""
139         return separator.join([query_string, current_embed_params])
140     return current_embed_params
141
```
--- 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/lib/streamlit/commands/query_params.py b/lib/streamlit/commands/query_params.py
--- a/lib/streamlit/commands/query_params.py
+++ b/lib/streamlit/commands/query_params.py
@@ -97,6 +97,7 @@
     msg.page_info_changed.query_string = _ensure_no_embed_params(
         query_params, ctx.query_string
     )
+    ctx.query_string = msg.page_info_changed.query_string
     ctx.enqueue(msg)

{"golden_diff": "diff --git a/lib/streamlit/commands/query_params.py b/lib/streamlit/commands/query_params.py\n--- a/lib/streamlit/commands/query_params.py\n+++ b/lib/streamlit/commands/query_params.py\n@@ -97,6 +97,7 @@\n     msg.page_info_changed.query_string = _ensure_no_embed_params(\n         query_params, ctx.query_string\n     )\n+    ctx.query_string = msg.page_info_changed.query_string\n     ctx.enqueue(msg)\n", "issue": " experimental_get_query_params  won't work before rerun \n### Checklist\n\n- [X] I have searched the [existing issues](https://github.com/streamlit/streamlit/issues) for similar issues.\n- [X] I added a very descriptive title to this issue.\n- [X] I have provided sufficient information below to help reproduce this issue.\n\n### Summary\n\nUser can not get right query_params before rerun.\n\n### Reproducible Code Example\n\n```Python\nimport streamlit as st\r\n\r\nst.experimental_set_query_params(param=3)\r\nst.write(st.experimental_get_query_params())\n```\n\n\n### Steps To Reproduce\n\nRun script, `{\"param \": 3}` will not appear at first time until rerun script after querystring in browser already changed.\n\n### Expected Behavior\n\nShow `{\"param \": 3}`\n\n### Current Behavior\n\nshow empty dict\n\n### Is this a regression?\n\n- [X] Yes, this used to work in a previous version.\n\n### Debug info\n\n- Streamlit version: 1.20.0\r\n- Python version: 3.10.6\r\n- Operating System: Linux\r\n- Browser: Chrome\r\n- Virtual environment: None\r\n\n\n### Additional Information\n\nIn previous version `set_query_params` will set `ctx.query_string = parse.urlencode(query_params, doseq=True)` immediately.\r\n\r\nBut in 1.20, this line is removed while `get_query_params` still get if from `ctx.query_string` .\n\n### Are you willing to submit a PR?\n\n- [x] Yes, I am willing to submit a PR!\n", "before_files": [{"content": "# Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022)\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport urllib.parse as parse\nfrom typing import Any, Dict, List\n\nfrom streamlit import util\nfrom streamlit.errors import StreamlitAPIException\nfrom streamlit.proto.ForwardMsg_pb2 import ForwardMsg\nfrom streamlit.runtime.metrics_util import gather_metrics\nfrom streamlit.runtime.scriptrunner import get_script_run_ctx\n\nEMBED_QUERY_PARAM = \"embed\"\nEMBED_OPTIONS_QUERY_PARAM = \"embed_options\"\nEMBED_QUERY_PARAMS_KEYS = [EMBED_QUERY_PARAM, EMBED_OPTIONS_QUERY_PARAM]\n\n\n@gather_metrics(\"experimental_get_query_params\")\ndef get_query_params() -> Dict[str, List[str]]:\n    \"\"\"Return the query parameters that is currently showing in the browser's URL bar.\n\n    Returns\n    -------\n    dict\n      The current query parameters as a dict. \"Query parameters\" are the part of the URL that comes\n      after the first \"?\".\n\n    Example\n    -------\n    Let's say the user's web browser is at\n    `http://localhost:8501/?show_map=True&selected=asia&selected=america`.\n    Then, you can get the query parameters using the following:\n\n    >>> import streamlit as st\n    >>>\n    >>> st.experimental_get_query_params()\n    {\"show_map\": [\"True\"], \"selected\": [\"asia\", \"america\"]}\n\n    Note that the values in the returned dict are *always* lists. This is\n    because we internally use Python's urllib.parse.parse_qs(), which behaves\n    this way. And this behavior makes sense when you consider that every item\n    in a query string is potentially a 1-element array.\n\n    \"\"\"\n    ctx = get_script_run_ctx()\n    if ctx is None:\n        return {}\n    # Return new query params dict, but without embed, embed_options query params\n    return util.exclude_key_query_params(\n        parse.parse_qs(ctx.query_string), keys_to_exclude=EMBED_QUERY_PARAMS_KEYS\n    )\n\n\n@gather_metrics(\"experimental_set_query_params\")\ndef set_query_params(**query_params: Any) -> None:\n    \"\"\"Set the query parameters that are shown in the browser's URL bar.\n\n    .. warning::\n        Query param `embed` cannot be set using this method.\n\n    Parameters\n    ----------\n    **query_params : dict\n        The query parameters to set, as key-value pairs.\n\n    Example\n    -------\n\n    To point the user's web browser to something like\n    \"http://localhost:8501/?show_map=True&selected=asia&selected=america\",\n    you would do the following:\n\n    >>> import streamlit as st\n    >>>\n    >>> st.experimental_set_query_params(\n    ...     show_map=True,\n    ...     selected=[\"asia\", \"america\"],\n    ... )\n\n    \"\"\"\n    ctx = get_script_run_ctx()\n    if ctx is None:\n        return\n\n    msg = ForwardMsg()\n    msg.page_info_changed.query_string = _ensure_no_embed_params(\n        query_params, ctx.query_string\n    )\n    ctx.enqueue(msg)\n\n\ndef _ensure_no_embed_params(\n    query_params: Dict[str, List[str]], query_string: str\n) -> str:\n    \"\"\"Ensures there are no embed params set (raises StreamlitAPIException) if there is a try,\n    also makes sure old param values in query_string are preserved. Returns query_string : str.\"\"\"\n    # Get query params dict without embed, embed_options params\n    query_params_without_embed = util.exclude_key_query_params(\n        query_params, keys_to_exclude=EMBED_QUERY_PARAMS_KEYS\n    )\n    if query_params != query_params_without_embed:\n        raise StreamlitAPIException(\n            \"Query param embed and embed_options (case-insensitive) cannot be set using set_query_params method.\"\n        )\n\n    all_current_params = parse.parse_qs(query_string)\n    current_embed_params = parse.urlencode(\n        {\n            EMBED_QUERY_PARAM: [\n                param\n                for param in util.extract_key_query_params(\n                    all_current_params, param_key=EMBED_QUERY_PARAM\n                )\n            ],\n            EMBED_OPTIONS_QUERY_PARAM: [\n                param\n                for param in util.extract_key_query_params(\n                    all_current_params, param_key=EMBED_OPTIONS_QUERY_PARAM\n                )\n            ],\n        },\n        doseq=True,\n    )\n    query_string = parse.urlencode(query_params, doseq=True)\n\n    if query_string:\n        separator = \"&\" if current_embed_params else \"\"\n        return separator.join([query_string, current_embed_params])\n    return current_embed_params\n", "path": "lib/streamlit/commands/query_params.py"}], "after_files": [{"content": "# Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022)\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport urllib.parse as parse\nfrom typing import Any, Dict, List\n\nfrom streamlit import util\nfrom streamlit.errors import StreamlitAPIException\nfrom streamlit.proto.ForwardMsg_pb2 import ForwardMsg\nfrom streamlit.runtime.metrics_util import gather_metrics\nfrom streamlit.runtime.scriptrunner import get_script_run_ctx\n\nEMBED_QUERY_PARAM = \"embed\"\nEMBED_OPTIONS_QUERY_PARAM = \"embed_options\"\nEMBED_QUERY_PARAMS_KEYS = [EMBED_QUERY_PARAM, EMBED_OPTIONS_QUERY_PARAM]\n\n\n@gather_metrics(\"experimental_get_query_params\")\ndef get_query_params() -> Dict[str, List[str]]:\n    \"\"\"Return the query parameters that is currently showing in the browser's URL bar.\n\n    Returns\n    -------\n    dict\n      The current query parameters as a dict. \"Query parameters\" are the part of the URL that comes\n      after the first \"?\".\n\n    Example\n    -------\n    Let's say the user's web browser is at\n    `http://localhost:8501/?show_map=True&selected=asia&selected=america`.\n    Then, you can get the query parameters using the following:\n\n    >>> import streamlit as st\n    >>>\n    >>> st.experimental_get_query_params()\n    {\"show_map\": [\"True\"], \"selected\": [\"asia\", \"america\"]}\n\n    Note that the values in the returned dict are *always* lists. This is\n    because we internally use Python's urllib.parse.parse_qs(), which behaves\n    this way. And this behavior makes sense when you consider that every item\n    in a query string is potentially a 1-element array.\n\n    \"\"\"\n    ctx = get_script_run_ctx()\n    if ctx is None:\n        return {}\n    # Return new query params dict, but without embed, embed_options query params\n    return util.exclude_key_query_params(\n        parse.parse_qs(ctx.query_string), keys_to_exclude=EMBED_QUERY_PARAMS_KEYS\n    )\n\n\n@gather_metrics(\"experimental_set_query_params\")\ndef set_query_params(**query_params: Any) -> None:\n    \"\"\"Set the query parameters that are shown in the browser's URL bar.\n\n    .. warning::\n        Query param `embed` cannot be set using this method.\n\n    Parameters\n    ----------\n    **query_params : dict\n        The query parameters to set, as key-value pairs.\n\n    Example\n    -------\n\n    To point the user's web browser to something like\n    \"http://localhost:8501/?show_map=True&selected=asia&selected=america\",\n    you would do the following:\n\n    >>> import streamlit as st\n    >>>\n    >>> st.experimental_set_query_params(\n    ...     show_map=True,\n    ...     selected=[\"asia\", \"america\"],\n    ... )\n\n    \"\"\"\n    ctx = get_script_run_ctx()\n    if ctx is None:\n        return\n\n    msg = ForwardMsg()\n    msg.page_info_changed.query_string = _ensure_no_embed_params(\n        query_params, ctx.query_string\n    )\n    ctx.query_string = msg.page_info_changed.query_string\n    ctx.enqueue(msg)\n\n\ndef _ensure_no_embed_params(\n    query_params: Dict[str, List[str]], query_string: str\n) -> str:\n    \"\"\"Ensures there are no embed params set (raises StreamlitAPIException) if there is a try,\n    also makes sure old param values in query_string are preserved. Returns query_string : str.\"\"\"\n    # Get query params dict without embed, embed_options params\n    query_params_without_embed = util.exclude_key_query_params(\n        query_params, keys_to_exclude=EMBED_QUERY_PARAMS_KEYS\n    )\n    if query_params != query_params_without_embed:\n        raise StreamlitAPIException(\n            \"Query param embed and embed_options (case-insensitive) cannot be set using set_query_params method.\"\n        )\n\n    all_current_params = parse.parse_qs(query_string)\n    current_embed_params = parse.urlencode(\n        {\n            EMBED_QUERY_PARAM: [\n                param\n                for param in util.extract_key_query_params(\n                    all_current_params, param_key=EMBED_QUERY_PARAM\n                )\n            ],\n            EMBED_OPTIONS_QUERY_PARAM: [\n                param\n                for param in util.extract_key_query_params(\n                    all_current_params, param_key=EMBED_OPTIONS_QUERY_PARAM\n                )\n            ],\n        },\n        doseq=True,\n    )\n    query_string = parse.urlencode(query_params, doseq=True)\n\n    if query_string:\n        separator = \"&\" if current_embed_params else \"\"\n        return separator.join([query_string, current_embed_params])\n    return current_embed_params\n", "path": "lib/streamlit/commands/query_params.py"}]}