-
Notifications
You must be signed in to change notification settings - Fork 706
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor modifications in upgrade and deployment forms #1283
Refactor modifications in upgrade and deployment forms #1283
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some small points and one big one: Can we please update past react 16.2 before doing this PR, so that we can use getDerivedStateFromProps
and stop adding componentWillReceiveProps
methods (which will need to be removed with effort very soon) or at least have to prefix them with UNSAFE_
and consider how we can avoid them.
dashboard/src/actions/charts.ts
Outdated
@@ -25,6 +25,13 @@ export const selectChartVersion = createAction("SELECT_CHART_VERSION", resolve = | |||
resolve({ chartVersion, values, schema }); | |||
}); | |||
|
|||
export const requestedDeployedChartversion = createAction("SELECTED_DEPLOYED_CHART_VERSION"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the different name from the string value here? (ie. why not selectedDeployedChartVersion
, matching the string action value, or updating the string value to "REQUESTED_..." to match)
Also, we really should have some standard here... I see requestCharts
/receiveCharts
(which makes sense as a pattern), while for another action it is selectChartVersions
/ receiveChartVersions
(select doesn't really make sense here, I think it's request?). Anyway, for this new one, can we do requestDeployedChartVersion
(ie. no ed
) and receiveDeployedChartVersion
(ie. matching requestCharts
/receiveCharts
) and possibly update the other action here (unless I'm missing why select
is being used).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you are right, I didn't properly read these
expect(wrapper.state("repo")).toEqual(repo); | ||
}); | ||
|
||
it("should request the deployed chart when teh app and repo are populated", () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tiny typo - s/teh/the/
|
||
export function getDeployedChartVersion( | ||
id: string, | ||
version: string, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there some confusion here about a chart version vs a chart revision, or are we defining a function called getDeployedChartVersion
which takes the chart version as input? confused
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, it's a bit confusing but it's the name pattern chosen here. The function needs a version as a string and returns a IChartVersion
which is all the information about that version. The difference with a IChart
is that IChart
contains a reference to the latest version instead of a specific version.
public componentDidMount() { | ||
const { releaseName, getAppWithUpdateInfo, namespace, fetchRepositories } = this.props; | ||
getAppWithUpdateInfo(releaseName, namespace); | ||
fetchRepositories(); | ||
} | ||
|
||
public componentWillReceiveProps(nextProps: IAppUpgradeProps) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We seem to keep adding more componentWillReceiveProps
when we should be removing them as we go, not adding?
See https://reactjs.org/docs/react-component.html#updating
The issue here is that we're adding more code that is dependent on detecting a change in the prop values, rather than working towards the functional getDerivedStateFromProps
. Even if we can't use that here (it's added in 16.3), let's not add code which we're going to have to remove/update in the future? We should be considering the reasons why react is removing componentWillReceiveProps
(ie. so that people won't be deriving state based on existing state or old prop values).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I completely forgot that componentWillReceiveProps
was the one being deprecated. In this case, I think it's okay to use componentDidUpdate
. I am reluctant to use getDerivedStateFromProps
since it's a bit complex (and we need to use componentDidUpdate anyway for the second part of this function)
if (nextProps.selected.version !== this.props.selected.version && !this.state.valuesModified) { | ||
this.setState({ appValues: nextProps.selected.values || "" }); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, this looks like we're adding more code which calculates state by detecting changes in props, rather than simply a function of the state... I worry we're going to pay for this later when componentWillReceiveProps
is no longer supported (it'll be removed in 1.17).
Can we first update to React 16.3 (at least, but possibly latest - 16.11), before we add more code like this? At least then we'll be able to use getDerivedStateFromProps
and will be forced to add UNSAFE_
to these unsafe methods we're adding?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the same here, it's true that we should not be using componentWillReceiveProps
but I prefer using componentDidUpdate
because the way to use it is more similar
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good.
@@ -41,6 +46,28 @@ class UpgradeForm extends React.Component<IUpgradeFormProps, IUpgradeFormState> | |||
valuesModified: false, | |||
}; | |||
|
|||
public componentWillReceiveProps(nextProps: IUpgradeFormProps) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto for getDerivedStateFromProps
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @absoludity, thanks for the review. It's true that we should not be using componentWillReceiveProps
but I'd rather use componentDidUpdate
which is the closest one. Let me know what you think.
dashboard/src/actions/charts.ts
Outdated
@@ -25,6 +25,13 @@ export const selectChartVersion = createAction("SELECT_CHART_VERSION", resolve = | |||
resolve({ chartVersion, values, schema }); | |||
}); | |||
|
|||
export const requestedDeployedChartversion = createAction("SELECTED_DEPLOYED_CHART_VERSION"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you are right, I didn't properly read these
|
||
export function getDeployedChartVersion( | ||
id: string, | ||
version: string, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, it's a bit confusing but it's the name pattern chosen here. The function needs a version as a string and returns a IChartVersion
which is all the information about that version. The difference with a IChart
is that IChart
contains a reference to the latest version instead of a specific version.
public componentDidMount() { | ||
const { releaseName, getAppWithUpdateInfo, namespace, fetchRepositories } = this.props; | ||
getAppWithUpdateInfo(releaseName, namespace); | ||
fetchRepositories(); | ||
} | ||
|
||
public componentWillReceiveProps(nextProps: IAppUpgradeProps) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I completely forgot that componentWillReceiveProps
was the one being deprecated. In this case, I think it's okay to use componentDidUpdate
. I am reluctant to use getDerivedStateFromProps
since it's a bit complex (and we need to use componentDidUpdate anyway for the second part of this function)
if (nextProps.selected.version !== this.props.selected.version && !this.state.valuesModified) { | ||
this.setState({ appValues: nextProps.selected.values || "" }); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the same here, it's true that we should not be using componentWillReceiveProps
but I prefer using componentDidUpdate
because the way to use it is more similar
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great, thanks for the update Andres.
repo = this.props.repo; | ||
if (repo && repo.metadata) { | ||
// If the repository comes from the properties, use it | ||
this.setState({ repo }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we storing props in the state like this? There should be no need if it's available in the props? Ah - I see below because it may not be in the props and may need to be fetched... so the state is guaranteed to have the repo?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exactly, the repo
will be only available in the props
when using the SelectRepoForm
if not, it's obtained from the app info. For simplicity, I stored it in the state.
this.setState({ repo: repoWithLatest }); | ||
repo = repoWithLatest; | ||
this.setState({ repo }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like 2 of these lines are redundant?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oops, yes
if (nextProps.selected.version !== this.props.selected.version && !this.state.valuesModified) { | ||
this.setState({ appValues: nextProps.selected.values || "" }); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good.
Follow up of #1278
This refactor:
IChartState
:deployed
. Instead of usingselected
and taking advantage that the first version selected is the one deployed, now we explicitly store that chart version in a different variable. This requires changes in the Redux store but allows us to pre-select the latest version in the upgrade form (not included in this PR)modifications
outside theBasicDeploymentFormBody
. This procedure is specific to the upgrade flow so it's now in theUpgradeForm
component.appValues
when changing the version is different between the deployment and the upgrade form, that's been extracted from theBasicDeploymentFormBody
as well. In the case of the deployment, we simply apply the default values of the new version while in the upgrade scenario we also apply modifications if they exist.