diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
 # Revision history for minilight-lua
 
+## 0.2.1.0 -- 2020-05-16
+
+* Support table type for useState
+
 ## 0.2.0.0 -- 2020-05-13
 
 * Some hooks supported:
diff --git a/minilight-lua.cabal b/minilight-lua.cabal
--- a/minilight-lua.cabal
+++ b/minilight-lua.cabal
@@ -4,7 +4,7 @@
 -- http://haskell.org/cabal/users-guide/
 
 name:                minilight-lua
-version:             0.2.0.0
+version:             0.2.1.0
 synopsis:            A binding library of minilight for Lua langauge.
 description:
   This library provides a way to write minilight component in Lua language.
diff --git a/src/MiniLight/Lua.hs b/src/MiniLight/Lua.hs
--- a/src/MiniLight/Lua.hs
+++ b/src/MiniLight/Lua.hs
@@ -14,6 +14,7 @@
 import qualified Data.Text.Encoding as TLE
 import Data.UnixTime
 import qualified Foreign.Lua as Lua
+import qualified Foreign.Lua.Types.Peekable as Lua
 import Foreign.Ptr
 import Foreign.C.String
 import Foreign.Marshal.Alloc
@@ -26,6 +27,43 @@
 import SDL.Font (Font)
 import Paths_minilight_lua
 
+data LuaValue
+  = LuaNil
+  | LuaBoolean Bool
+  | LuaString T.Text
+  | LuaNumber Double
+  | LuaTable Table
+  deriving (Read, Show)
+
+newtype Table = Table [(LuaValue, LuaValue)]
+  deriving (Read, Show)
+
+instance Lua.Peekable LuaValue where
+  peek i = do
+    ltype <- Lua.ltype i
+    case ltype of
+      Lua.TypeNil -> return LuaNil
+      Lua.TypeBoolean -> fmap LuaBoolean $ Lua.toboolean i
+      Lua.TypeNumber -> fmap (\(Just (Lua.Number v)) -> LuaNumber v) $ Lua.tonumber i
+      Lua.TypeString -> fmap (\(Just v) -> LuaString $ TLE.decodeUtf8 v) $ Lua.tostring i
+      Lua.TypeTable -> fmap LuaTable $ Lua.peek i
+
+instance Lua.Pushable LuaValue where
+  push val = case val of
+    LuaNil -> Lua.pushnil
+    LuaBoolean b -> Lua.pushboolean b
+    LuaString t -> Lua.pushstring $ TLE.encodeUtf8 t
+    LuaNumber d -> Lua.pushnumber $ Lua.Number d
+    LuaTable t -> Lua.push t
+
+instance Lua.Peekable Table where
+  peek i = fmap Table $ Lua.peekKeyValuePairs i
+
+instance Lua.Pushable Table where
+  push (Table kv) = do
+    Lua.newtable
+    mapM_ (\(k,v) -> Lua.push k *> Lua.push v *> Lua.rawset (-3)) kv
+
 data LuaComponentState = LuaComponentState {
   mousePosition :: IORef (V2 Int),
   mousePressed :: IORef Bool,
@@ -36,6 +74,7 @@
   numberStates :: IORef (M.Map String (Ptr Double)),
   boolStates :: IORef (M.Map String (Ptr Bool)),
   stringStates :: IORef (M.Map String (Ptr CString)),
+  tableStates :: IORef (M.Map String (Ptr CString)),
 
   -- Luaでの更新判定用
   updatedAtRef :: IORef UnixTime
@@ -99,6 +138,7 @@
   ns  <- newIORef M.empty
   bs  <- newIORef M.empty
   ss  <- newIORef M.empty
+  ts  <- newIORef M.empty
   u   <- newIORef $ UnixTime 0 0
 
   let state = LuaComponentState
@@ -111,6 +151,7 @@
         , numberStates  = ns
         , boolStates    = bs
         , stringStates  = ss
+        , tableStates   = ts
         , updatedAtRef  = u
         }
 
@@ -173,6 +214,9 @@
     Lua.addfunction "newState_number"   minilight_newStateNumber
     Lua.addfunction "readState_number"  minilight_readStateNumber
     Lua.addfunction "writeState_number" minilight_writeStateNumber
+    Lua.addfunction "newState_table"    minilight_newStateTable
+    Lua.addfunction "readState_table"   minilight_readStateTable
+    Lua.addfunction "writeState_table"  minilight_writeStateTable
 
   Lua.requirehs "minilight" $ do
     lib <- liftIO $ getDataFileName "src/lib.lua"
@@ -267,3 +311,28 @@
 
   minilight_writeStateNumber :: Ptr Double -> Lua.Number -> Lua.Lua ()
   minilight_writeStateNumber p (Lua.Number v) = liftIO $ poke p v
+
+  minilight_newStateTable :: Int -> Table -> Lua.Lua (Ptr CString)
+  minilight_newStateTable index def = liftIO $ do
+    m   <- readIORef $ tableStates state
+    uat <- readIORef $ updatedAtRef state
+    let key = show uat ++ "-" ++ show index
+    case m M.!? key of
+      Just k  -> return k
+      Nothing -> do
+        p  <- malloc
+        cs <- newCString $ show def
+        poke p cs
+        writeIORef (tableStates state) $ M.insert key p m
+        return p
+
+  minilight_readStateTable :: Ptr CString -> Lua.Lua Table
+  minilight_readStateTable p = liftIO $ do
+    cs <- peek p
+    fmap read $ peekCString cs
+
+  minilight_writeStateTable :: Ptr CString -> Table -> Lua.Lua ()
+  minilight_writeStateTable p val = liftIO $ do
+    peek p >>= free
+    cs <- newCString $ show val
+    poke p cs
diff --git a/src/lib.lua b/src/lib.lua
--- a/src/lib.lua
+++ b/src/lib.lua
@@ -34,6 +34,15 @@
                 return minilight_raw.writeState_bool(ref, v)
             end
         }
+    elseif (type(def) == "table") then
+        local ref = minilight_raw.newState_table(index, def)
+
+        return {
+            value = minilight_raw.readState_table(ref),
+            write = function(v)
+                return minilight_raw.writeState_table(ref, v)
+            end
+        }
     else
         error("Type(" .. type(def) .. ") is not supported!")
     end
