[Work in progress] A Reactjs-based web app to help with ricing: designing beautiful unix desktop environments.
git clone https://mcol.xyz/code/unix.sexy
Log | Files | Refs

commit 9b9c3120cb250f431ca2bd5a95d56b89ec89c628
parent 97ddac39e97ff65cc74e263fc773c4cfcc81ed36
Author: mcol <mcol@posteo.net>
Date:   Sat,  6 Jun 2020 19:22:29 +0100

convert Tabs to function component

Diffstat:
Dsrc/features/tabs/Tab.js | 43-------------------------------------------
Dsrc/features/tabs/Tabs.js | 61-------------------------------------------------------------
Asrc/features/tabs/index.js | 50++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/features/tabs/slice.js | 20++++++++++++++++++++
Msrc/store.js | 21++++++++++++---------
5 files changed, 82 insertions(+), 113 deletions(-)

diff --git a/src/features/tabs/Tab.js b/src/features/tabs/Tab.js @@ -1,43 +0,0 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; - - -class Tab extends Component { - static propTypes = { - activeTab: PropTypes.string.isRequired, - label: PropTypes.string.isRequired, - onClick: PropTypes.func.isRequired, - }; - - onClick = () => { - const { label, onClick } = this.props; - onClick(label); - } - - render() { - const { - onClick, - props: { - activeTab, - label, - }, - } = this; - - let className = 'tab-list-item'; - - if (activeTab === label) { - className += ' tab-list-active'; - } - - return ( - <li - className={className} - onClick={onClick} - > - {label} - </li> - ); - } -} - -export default Tab; diff --git a/src/features/tabs/Tabs.js b/src/features/tabs/Tabs.js @@ -1,61 +0,0 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; - -import Tab from './Tab'; - -class Tabs extends Component { - static propTypes = { - children: PropTypes.instanceOf(Array).isRequired, - } - - constructor(props) { - super(props); - - this.state = { - activeTab: this.props.children[0].props.label, - }; - } - - onClickTabItem = (tab) => { - this.setState({ activeTab: tab }); - } - - render() { - const { - onClickTabItem, - props: { - children, - }, - state: { - activeTab, - } - } = this; - - return ( - <div className="tabs"> - <ol className="tab-list"> - {children.map((child) => { - const { label } = child.props; - - return ( - <Tab - activeTab={activeTab} - key={label} - label={label} - onClick={onClickTabItem} - /> - ); - })} - </ol> - <div className="tab-content"> - {children.map((child) => { - if (child.props.label !== activeTab) return undefined; - return child.props.children; - })} - </div> - </div> - ); - } -} - -export default Tabs; diff --git a/src/features/tabs/index.js b/src/features/tabs/index.js @@ -0,0 +1,50 @@ +import React from 'react'; +import { useDispatch, useSelector } from 'react-redux'; + +import { selectTab, setTab } from './slice'; + + +export default function Tabs(props) { + const active = useSelector(selectTab); + + return ( + <div className="tabs"> + <TabList + active={active} + children={props.children} + /> + + <div className="tab-content"> + {props.children[active].props.children} + </div> + </div> + ); +} + + +function TabList(props) { + const dispatch = useDispatch(); + + return ( + <ol className="tab-list"> + {props.children.map((child, i) => { + const { label } = child.props; + + let className = 'tab-list-item'; + if (props.active === i) { + className += ' tab-list-active'; + } + + return ( + <li + className={className} + onClick={() => dispatch(setTab(i))} + key={label} + > + {label} + </li> + ); + })} + </ol> + ) +} diff --git a/src/features/tabs/slice.js b/src/features/tabs/slice.js @@ -0,0 +1,20 @@ +import { createSlice } from '@reduxjs/toolkit'; + + +const tabSlice = createSlice({ + name: 'tab', + + initialState: { + index: 0 + }, + + reducers: { + setTab: (state, tab) => { + state.index = tab.payload; + }, + }, +}); + +export const { setTab } = tabSlice.actions; +export const selectTab = state => state.tab.index; +export default tabSlice.reducer; diff --git a/src/store.js b/src/store.js @@ -5,25 +5,28 @@ import storage from 'redux-persist/lib/storage'; import { RESET } from './features/reset'; import backgroundReducer from './features/background/slice'; import windowReducer from './features/windows/slice'; +import tabReducer from './features/tabs/slice'; const reducer = combineReducers({ - background: backgroundReducer, - windows: windowReducer, + background: backgroundReducer, + windows: windowReducer, + tab: tabReducer, }) const rootReducer = (state, action) => { - if (action.type === RESET) { - storage.removeItem('persist:root') - state = undefined; - } - return reducer(state, action); + if (action.type === RESET) { + storage.removeItem('persist:root') + state = undefined; + } + return reducer(state, action); }; const persistConfig = { - key: 'root', - storage, + key: 'root', + storage, + whitelist: [], } const persistedReducer = persistReducer(persistConfig, rootReducer)