mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 09:57:02 +01:00
Remove unused PersistentForm (#7770)
This component used to persist form contents to LocalStorage. This was especially useful for the popup UI, as each time the mouse left the popup, the UI was completely torn down and state was lost. This component was only being referenced by one form, and it wasn't even being used there (e.g. no fields were labelled appropriately to be persisted). This was a useful component, and it seems this feature was lost somewhere in the past couple of years. It was tempting to re-instate it rather than delete it, but I decided not to because I'd likely approach the problem differently if we wanted to reinstate it again today (maybe by using a React Hook, or storing the state in Redux and persisting a subset of the Redux store instead).
This commit is contained in:
parent
fa1482ef76
commit
0d61f78379
@ -1,28 +0,0 @@
|
|||||||
# Form Persisting Architecture
|
|
||||||
|
|
||||||
Since:
|
|
||||||
- The popup is torn down completely on every click outside of it.
|
|
||||||
- We have forms with multiple fields (like passwords & seed phrases) that might encourage a user to leave our panel to refer to a password manager.
|
|
||||||
|
|
||||||
We cause user friction when we lose the contents of certain forms.
|
|
||||||
|
|
||||||
This calls for an architecture of a form component that can completely persist its values to LocalStorage on every relevant change, and restore those values on reopening.
|
|
||||||
|
|
||||||
To achieve this, we have defined a class, a subclass of `React.Component`, called `PersistentForm`, and it's stored at `ui/lib/persistent-form.js`.
|
|
||||||
|
|
||||||
To use this class, simply take your form component (the component that renders `input`, `select`, or `textarea` elements), and make it subclass from `PersistentForm` instead of `React.Component`.
|
|
||||||
|
|
||||||
You can see an example of this in use in `ui/app/first-time/restore-vault.js`.
|
|
||||||
|
|
||||||
Additionally, any field whose value should be persisted, should have a `persistentFormId` attribute, which needs to be assigned under a `dataset` key on the main `attributes` hash. For example:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
return h('textarea.twelve-word-phrase.letter-spacey', {
|
|
||||||
dataset: {
|
|
||||||
persistentFormId: 'wallet-seed',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
That's it! This field should be persisted to `localStorage` on each `keyUp`, those values should be restored on view load, and the cached values should be cleared when navigating deliberately away from the form.
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
|||||||
import React from 'react'
|
import React, { Component } from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import PersistentForm from '../../../lib/persistent-form'
|
|
||||||
import {
|
import {
|
||||||
getAmountErrorObject,
|
getAmountErrorObject,
|
||||||
getGasFeeErrorObject,
|
getGasFeeErrorObject,
|
||||||
@ -16,7 +15,7 @@ import SendFooter from './send-footer'
|
|||||||
import EnsInput from './send-content/add-recipient/ens-input'
|
import EnsInput from './send-content/add-recipient/ens-input'
|
||||||
|
|
||||||
|
|
||||||
export default class SendTransactionScreen extends PersistentForm {
|
export default class SendTransactionScreen extends Component {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
addressBook: PropTypes.arrayOf(PropTypes.object),
|
addressBook: PropTypes.arrayOf(PropTypes.object),
|
||||||
|
@ -1,62 +0,0 @@
|
|||||||
import { inherits } from 'util'
|
|
||||||
import { Component } from 'react'
|
|
||||||
|
|
||||||
const defaultKey = 'persistent-form-default'
|
|
||||||
const eventName = 'keyup'
|
|
||||||
|
|
||||||
export default PersistentForm
|
|
||||||
|
|
||||||
function PersistentForm () {
|
|
||||||
Component.call(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
inherits(PersistentForm, Component)
|
|
||||||
|
|
||||||
PersistentForm.prototype.componentDidMount = function () {
|
|
||||||
const fields = document.querySelectorAll('[data-persistent-formid]')
|
|
||||||
const store = this.getPersistentStore()
|
|
||||||
|
|
||||||
for (let i = 0; i < fields.length; i++) {
|
|
||||||
const field = fields[i]
|
|
||||||
const key = field.getAttribute('data-persistent-formid')
|
|
||||||
const cached = store[key]
|
|
||||||
if (cached !== undefined) {
|
|
||||||
field.value = cached
|
|
||||||
}
|
|
||||||
|
|
||||||
field.addEventListener(eventName, this.persistentFieldDidUpdate.bind(this))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PersistentForm.prototype.getPersistentStore = function () {
|
|
||||||
let store = window.localStorage[this.persistentFormParentId || defaultKey]
|
|
||||||
if (store && store !== 'null') {
|
|
||||||
store = JSON.parse(store)
|
|
||||||
} else {
|
|
||||||
store = {}
|
|
||||||
}
|
|
||||||
return store
|
|
||||||
}
|
|
||||||
|
|
||||||
PersistentForm.prototype.setPersistentStore = function (newStore) {
|
|
||||||
window.localStorage[this.persistentFormParentId || defaultKey] = JSON.stringify(newStore)
|
|
||||||
}
|
|
||||||
|
|
||||||
PersistentForm.prototype.persistentFieldDidUpdate = function (event) {
|
|
||||||
const field = event.target
|
|
||||||
const store = this.getPersistentStore()
|
|
||||||
const key = field.getAttribute('data-persistent-formid')
|
|
||||||
const val = field.value
|
|
||||||
store[key] = val
|
|
||||||
this.setPersistentStore(store)
|
|
||||||
}
|
|
||||||
|
|
||||||
PersistentForm.prototype.componentWillUnmount = function () {
|
|
||||||
const fields = document.querySelectorAll('[data-persistent-formid]')
|
|
||||||
for (let i = 0; i < fields.length; i++) {
|
|
||||||
const field = fields[i]
|
|
||||||
field.removeEventListener(eventName, this.persistentFieldDidUpdate.bind(this))
|
|
||||||
}
|
|
||||||
this.setPersistentStore({})
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user