Skip to content

Commit

Permalink
Fix setProps when IDs aren't provided (#166)
Browse files Browse the repository at this point in the history
provide valid setProps for all components, even if they don't have an ID

construct paths on-the-fly while recursing through the tree.
  • Loading branch information
chriddyp committed Apr 22, 2019
1 parent f5c1a1f commit ab4d2d8
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 15 deletions.
4 changes: 3 additions & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,16 @@ jobs:
name: Install dependencies (dash)
command: |
git clone git@github.com:plotly/dash.git
git clone --branch fix-prop-types git@github.com:plotly/dash-core-components.git
git clone git@github.com:plotly/dash-core-components.git
git clone git@github.com:plotly/dash-html-components.git
git clone git@github.com:plotly/dash-table.git
git clone git@github.com:plotly/dash-renderer-test-components
. venv/bin/activate
pip install -e ./dash --quiet
cd dash-core-components && npm install --ignore-scripts && npm run build && pip install -e . && cd ..
cd dash-html-components && npm install --ignore-scripts && npm run build && pip install -e . && cd ..
cd dash-table && npm install --ignore-scripts && npm run build && pip install -e . && cd ..
cd dash-renderer-test-components && npm install --ignore-scripts && npm run build:all && pip install -e . && cd ..
- run:
name: Build
Expand Down
12 changes: 10 additions & 2 deletions src/APIController.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,19 @@ class UnconnectedContainer extends Component {
) {
return (
<GlobalErrorContainer>
<TreeContainer _dashprivate_layout={layout} />
<TreeContainer
_dashprivate_layout={layout}
_dashprivate_path={[]}
/>
</GlobalErrorContainer>
);
} else if (appLifecycle === getAppState('HYDRATED')) {
return <TreeContainer _dashprivate_layout={layout} />;
return (
<TreeContainer
_dashprivate_layout={layout}
_dashprivate_path={[]}
/>
);
}

return <div className="_dash-loading">{'Loading...'}</div>;
Expand Down
28 changes: 16 additions & 12 deletions src/TreeContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import Registry from './registry';
import {propTypeErrorHandler} from './exceptions';
import {connect} from 'react-redux';
import {
addIndex,
any,
concat,
contains,
filter,
forEach,
Expand Down Expand Up @@ -50,11 +52,12 @@ function validateComponent(componentDefinition) {
}
}

const createContainer = component => isSimpleComponent(component) ?
const createContainer = (component, path) => isSimpleComponent(component) ?
component :
(<AugmentedTreeContainer
key={component && component.props && component.props.id}
_dashprivate_layout={component}
_dashprivate_path={path}
/>);

function CheckedComponent(p) {
Expand Down Expand Up @@ -87,14 +90,16 @@ CheckedComponent.propTypes = {
id: PropTypes.string,
};
class TreeContainer extends Component {
getChildren(components) {
getChildren(components, path) {
if (isNil(components)) {
return null;
}

return Array.isArray(components) ?
map(createContainer, components) :
createContainer(components);
addIndex(map)(
(component, i) => createContainer(component, concat(path, ['props', 'children', i])),
components
) : createContainer(components, concat(path, ['props', 'children']));
}

getComponent(_dashprivate_layout, children, loading_state, setProps) {
Expand Down Expand Up @@ -148,7 +153,7 @@ class TreeContainer extends Component {
const {
_dashprivate_dependencies,
_dashprivate_dispatch,
_dashprivate_paths
_dashprivate_path
} = this.props;

const id = this.getLayoutProps().id;
Expand All @@ -165,8 +170,7 @@ class TreeContainer extends Component {
// Always update this component's props
_dashprivate_dispatch(updateProps({
props: newProps,
id: id,
itempath: _dashprivate_paths[id]
itempath: _dashprivate_path
}));

// Only dispatch changes to Dash if a watched prop changed
Expand Down Expand Up @@ -194,12 +198,13 @@ class TreeContainer extends Component {
const {
_dashprivate_dispatch,
_dashprivate_layout,
_dashprivate_loadingState
_dashprivate_loadingState,
_dashprivate_path
} = this.props;

const layoutProps = this.getLayoutProps();

const children = this.getChildren(layoutProps.children);
const children = this.getChildren(layoutProps.children, _dashprivate_path);
const setProps = this.getSetProps(_dashprivate_dispatch);

return this.getComponent(_dashprivate_layout, children, _dashprivate_loadingState, setProps);
Expand All @@ -211,9 +216,9 @@ TreeContainer.propTypes = {
_dashprivate_dispatch: PropTypes.func,
_dashprivate_layout: PropTypes.object,
_dashprivate_loadingState: PropTypes.object,
_dashprivate_paths: PropTypes.any,
_dashprivate_requestQueue: PropTypes.any,
_dashprivate_config: PropTypes.object,
_dashprivate_path: PropTypes.array,
};

function isLoadingComponent(layout) {
Expand Down Expand Up @@ -286,7 +291,6 @@ function getLoadingState(layout, requestQueue) {
export const AugmentedTreeContainer = connect(
state => ({
dependencies: state.dependenciesRequest.content,
paths: state.paths,
requestQueue: state.requestQueue,
config: state.config
}),
Expand All @@ -295,8 +299,8 @@ export const AugmentedTreeContainer = connect(
_dashprivate_dependencies: stateProps.dependencies,
_dashprivate_dispatch: dispatchProps.dispatch,
_dashprivate_layout: ownProps._dashprivate_layout,
_dashprivate_path: ownProps._dashprivate_path,
_dashprivate_loadingState: getLoadingState(ownProps._dashprivate_layout, stateProps.requestQueue),
_dashprivate_paths: stateProps.paths,
_dashprivate_requestQueue: stateProps.requestQueue,
_dashprivate_config: stateProps.config,
})
Expand Down
30 changes: 30 additions & 0 deletions tests/test_render.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from dash.development.base_component import Component
import dash_html_components as html
import dash_core_components as dcc
import dash_renderer_test_components

from bs4 import BeautifulSoup
from selenium.webdriver.common.action_chains import ActionChains
Expand Down Expand Up @@ -2960,3 +2961,32 @@ def display_content(pathname):
test_cases[test_case_id]['name']
)
)

def test_set_props_behavior(self):
app = dash.Dash(__name__)
app.layout = html.Div([
dash_renderer_test_components.UncontrolledInput(
id='id',
value=''
),
html.Div(
id='container',
children=dash_renderer_test_components.UncontrolledInput(
value=''
),
)
])

self.startServer(
app,
debug=True,
use_reloader=False,
use_debugger=True,
dev_tools_hot_reload=False,
)

self.wait_for_element_by_css_selector('#id').send_keys('hello input with ID')
self.wait_for_text_to_equal('#id', 'hello input with ID')

self.wait_for_element_by_css_selector('#container input').send_keys('hello input without ID')
self.wait_for_text_to_equal('#container input', 'hello input without ID')

0 comments on commit ab4d2d8

Please sign in to comment.