diff --git a/@plotly/dash-test-components/src/components/ArrayOfExactOrShapeWithNodePropAssignNone.js b/@plotly/dash-test-components/src/components/ArrayOfExactOrShapeWithNodePropAssignNone.js new file mode 100644 index 0000000000..9e01f9b730 --- /dev/null +++ b/@plotly/dash-test-components/src/components/ArrayOfExactOrShapeWithNodePropAssignNone.js @@ -0,0 +1,30 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +const ArrayOfExactOrShapeWithNodePropAssignNone = (props) => { + const { id, test_array_of_exact_prop, test_array_of_shape_prop } = props; + + return ( +
+ {`length of test_array_of_exact_prop: ${(test_array_of_exact_prop || []).length}, length of test_array_of_shape_prop: ${(test_array_of_shape_prop || []).length}`} +
+ ); +}; + +ArrayOfExactOrShapeWithNodePropAssignNone.propTypes = { + id: PropTypes.string, + test_array_of_exact_prop: PropTypes.arrayOf( + PropTypes.exact({ + label: PropTypes.node, + value: PropTypes.string + }) + ), + test_array_of_shape_prop: PropTypes.arrayOf( + PropTypes.shape({ + label: PropTypes.node, + value: PropTypes.string + }) + ) +}; + +export default ArrayOfExactOrShapeWithNodePropAssignNone; diff --git a/@plotly/dash-test-components/src/index.js b/@plotly/dash-test-components/src/index.js index 76e88310a8..bdddfc18b5 100644 --- a/@plotly/dash-test-components/src/index.js +++ b/@plotly/dash-test-components/src/index.js @@ -12,6 +12,7 @@ import DrawCounter from './components/DrawCounter'; import AddPropsComponent from "./components/AddPropsComponent"; import ReceivePropsComponent from "./components/ReceivePropsComponent"; import ShapeOrExactKeepOrderComponent from "./components/ShapeOrExactKeepOrderComponent"; +import ArrayOfExactOrShapeWithNodePropAssignNone from './components/ArrayOfExactOrShapeWithNodePropAssignNone'; export { @@ -27,5 +28,6 @@ export { DrawCounter, AddPropsComponent, ReceivePropsComponent, - ShapeOrExactKeepOrderComponent + ShapeOrExactKeepOrderComponent, + ArrayOfExactOrShapeWithNodePropAssignNone }; diff --git a/CHANGELOG.md b/CHANGELOG.md index 5237b2687b..f0de006ace 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ This project adheres to [Semantic Versioning](https://semver.org/). ## Fixed - [#2994](https://github.com/plotly/dash/pull/2994) Keep generated doc-string order for shape or exact props. Fixes [#2990](https://github.com/plotly/dash/issues/2990) +- [#3011](https://github.com/plotly/dash/pull/3011) Fixed an exception error caused by assigning `None` to array properties with `exact` or `shape` element types. Fixes [#3010](https://github.com/plotly/dash/issues/3010) ## [2.18.1] - 2024-09-12 diff --git a/dash/dash-renderer/src/TreeContainer.js b/dash/dash-renderer/src/TreeContainer.js index 357c24d5b2..25b51bc493 100644 --- a/dash/dash-renderer/src/TreeContainer.js +++ b/dash/dash-renderer/src/TreeContainer.js @@ -322,7 +322,7 @@ class BaseTreeContainer extends Component { }); node = rpath(frontPath, props); - if (node === undefined || !node.length) { + if (node === undefined || !node?.length) { continue; } const firstNode = rpath(backPath, node[0]); diff --git a/tests/integration/renderer/test_array_of_exact_or_shape_with_node_prop_assign_none.py b/tests/integration/renderer/test_array_of_exact_or_shape_with_node_prop_assign_none.py new file mode 100644 index 0000000000..ddfd8f86e1 --- /dev/null +++ b/tests/integration/renderer/test_array_of_exact_or_shape_with_node_prop_assign_none.py @@ -0,0 +1,31 @@ +from dash import Dash, html + +from dash_test_components import ArrayOfExactOrShapeWithNodePropAssignNone + + +def test_aoeoswnpsn001_array_of_exact_or_shape_with_node_prop_assign_none(dash_duo): + app = Dash(__name__) + app.layout = html.Div( + [ + ArrayOfExactOrShapeWithNodePropAssignNone( + id="test-component1", + test_array_of_exact_prop=[{"label": c, "value": c} for c in "abc"], + test_array_of_shape_prop=[{"label": c, "value": c} for c in "abc"], + ), + ArrayOfExactOrShapeWithNodePropAssignNone( + id="test-component2", + test_array_of_exact_prop=None, + test_array_of_shape_prop=None, + ), + ] + ) + + dash_duo.start_server(app) + dash_duo.wait_for_text_to_equal( + "#test-component1", + "length of test_array_of_exact_prop: 3, length of test_array_of_shape_prop: 3", + ) + dash_duo.wait_for_text_to_equal( + "#test-component2", + "length of test_array_of_exact_prop: 0, length of test_array_of_shape_prop: 0", + )