1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 09:52:26 +01:00

Refactor token list click handler (#8234)

The token list click handler has been moved up from the token cell to
the wallet view component where the token list is used. This keeps the
responsibilities of the token list and token cell components a bit more
focused - they're now only responsible for display, not what the
effects of clicking should be.
This commit is contained in:
Mark Stacey 2020-03-25 18:24:14 -03:00 committed by GitHub
parent 19c58b2f32
commit ade737e2a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 56 additions and 40 deletions

View File

@ -14,14 +14,12 @@ export default class TokenCell extends Component {
address: PropTypes.string,
symbol: PropTypes.string,
string: PropTypes.string,
setSelectedToken: PropTypes.func.isRequired,
selectedTokenAddress: PropTypes.string,
contractExchangeRates: PropTypes.object,
conversionRate: PropTypes.number,
hideSidebar: PropTypes.func.isRequired,
sidebarOpen: PropTypes.bool,
currentCurrency: PropTypes.string,
image: PropTypes.string,
onClick: PropTypes.func.isRequired,
}
state = {
@ -34,12 +32,10 @@ export default class TokenCell extends Component {
address,
symbol,
string,
setSelectedToken,
selectedTokenAddress,
contractExchangeRates,
conversionRate,
hideSidebar,
sidebarOpen,
onClick,
currentCurrency,
image,
} = this.props
@ -71,17 +67,7 @@ export default class TokenCell extends Component {
className={classnames(`token-list-item`, {
'token-list-item--active': selectedTokenAddress === address,
})}
onClick={() => {
setSelectedToken(address)
this.context.metricsEvent({
eventOpts: {
category: 'Navigation',
action: 'Token Menu',
name: 'Clicked Token',
},
})
selectedTokenAddress !== address && sidebarOpen && hideSidebar()
}}
onClick={onClick.bind(null, address)}
>
<Identicon
className="token-list-item__identicon"

View File

@ -1,5 +1,4 @@
import { connect } from 'react-redux'
import { setSelectedToken, hideSidebar } from '../../../store/actions'
import TokenCell from './token-cell.component'
function mapStateToProps (state) {
@ -8,15 +7,7 @@ function mapStateToProps (state) {
conversionRate: state.metamask.conversionRate,
currentCurrency: state.metamask.currentCurrency,
selectedTokenAddress: state.metamask.selectedTokenAddress,
sidebarOpen: state.appState.sidebar.isOpen,
}
}
function mapDispatchToProps (dispatch) {
return {
setSelectedToken: (address) => dispatch(setSelectedToken(address)),
hideSidebar: () => dispatch(hideSidebar()),
}
}
export default connect(mapStateToProps, mapDispatchToProps)(TokenCell)
export default connect(mapStateToProps)(TokenCell)

View File

@ -4,6 +4,7 @@ import thunk from 'redux-thunk'
import { Provider } from 'react-redux'
import configureMockStore from 'redux-mock-store'
import { mount } from 'enzyme'
import sinon from 'sinon'
import TokenCell from '.'
import Identicon from '../../ui/identicon'
@ -32,7 +33,10 @@ describe('Token Cell', function () {
const mockStore = configureMockStore(middlewares)
const store = mockStore(state)
let onClick
beforeEach(function () {
onClick = sinon.stub()
wrapper = mount(
<Provider store={store}>
<TokenCell
@ -41,11 +45,16 @@ describe('Token Cell', function () {
string="5.000"
currentCurrency="usd"
image="./test-image"
onClick={onClick}
/>
</Provider>
)
})
afterEach(function () {
sinon.restore()
})
it('renders Identicon with props from token cell', function () {
assert.equal(wrapper.find(Identicon).prop('address'), '0xAnotherToken')
assert.equal(wrapper.find(Identicon).prop('image'), './test-image')
@ -63,4 +72,9 @@ describe('Token Cell', function () {
assert.equal(wrapper.find('.token-list-item__fiat-amount').text(), '0.52 USD')
})
it('calls onClick when clicked', function () {
assert.ok(!onClick.called)
wrapper.simulate('click')
assert.ok(onClick.called)
})
})

View File

@ -36,6 +36,7 @@ class TokenList extends Component {
userAddress: PropTypes.string.isRequired,
network: PropTypes.string.isRequired,
assetImages: PropTypes.object.isRequired,
onTokenClick: PropTypes.func.isRequired,
}
state = {
@ -121,7 +122,7 @@ class TokenList extends Component {
}
render () {
const { userAddress, assetImages } = this.props
const { userAddress, assetImages, onTokenClick } = this.props
const { tokens, isLoading, error } = this.state
if (isLoading) {
return (
@ -172,7 +173,7 @@ class TokenList extends Component {
{tokens.map((tokenData, index) => {
tokenData.image = assetImages[tokenData.address]
return (
<TokenCell key={index} {...tokenData} />
<TokenCell key={index} {...tokenData} onClick={onTokenClick} />
)
})}
</div>
@ -180,4 +181,10 @@ class TokenList extends Component {
}
}
export default connect(mapStateToProps)(TokenList)
const TokenListContainer = connect(mapStateToProps)(TokenList)
TokenListContainer.propTypes = {
onTokenClick: PropTypes.func.isRequired,
}
export default TokenListContainer

View File

@ -22,16 +22,17 @@ export default class WalletView extends Component {
}
static propTypes = {
selectedTokenAddress: PropTypes.string,
selectedAccount: PropTypes.object,
selectedAddress: PropTypes.string.isRequired,
hideSidebar: PropTypes.func.isRequired,
history: PropTypes.object.isRequired,
identities: PropTypes.object.isRequired,
keyrings: PropTypes.array.isRequired,
responsiveDisplayClassname: PropTypes.string,
identities: PropTypes.object.isRequired,
history: PropTypes.object.isRequired,
unsetSelectedToken: PropTypes.func.isRequired,
selectedAccount: PropTypes.object,
selectedAddress: PropTypes.string.isRequired,
selectedTokenAddress: PropTypes.string,
setSelectedToken: PropTypes.func.isRequired,
sidebarOpen: PropTypes.bool.isRequired,
hideSidebar: PropTypes.func.isRequired,
unsetSelectedToken: PropTypes.func.isRequired,
}
renderWalletBalance () {
@ -105,10 +106,14 @@ export default class WalletView extends Component {
render () {
const {
hideSidebar,
identities,
keyrings,
responsiveDisplayClassname,
selectedAddress,
keyrings,
identities,
selectedTokenAddress,
setSelectedToken,
sidebarOpen,
} = this.props
const checksummedAddress = checksumAddress(selectedAddress)
@ -139,7 +144,19 @@ export default class WalletView extends Component {
showConnectedSites={this.showConnectedSites}
/>
{this.renderWalletBalance()}
<TokenList />
<TokenList
onTokenClick={(tokenAddress) => {
setSelectedToken(tokenAddress)
this.context.metricsEvent({
eventOpts: {
category: 'Navigation',
action: 'Token Menu',
name: 'Clicked Token',
},
})
selectedTokenAddress !== tokenAddress && sidebarOpen && hideSidebar()
}}
/>
{this.renderAddToken()}
</div>
)

View File

@ -19,6 +19,7 @@ function mapStateToProps (state) {
function mapDispatchToProps (dispatch) {
return {
hideSidebar: () => dispatch(hideSidebar()),
setSelectedToken: (tokenAddress) => dispatch(setSelectedToken(tokenAddress)),
unsetSelectedToken: () => dispatch(setSelectedToken()),
}
}