React-Redux Hooks 中文

原文:https://react-redux.js.org/api/hooks

翻譯水平有待提高,虛心接受各位看官的指教,歡迎大家留言自己的見(jiàn)解

目錄

1.在React Redux應(yīng)用中使用Hooks
2.useSelector()
3.useDispatch()
4.useStore()
5.自定義 context
6.注意事項(xiàng)
7.Hooks 示例

簡(jiǎn)介

React的新特性 Hooks讓函數(shù)組件可以使用類(lèi)似Class組件的State等執(zhí)行副作用。React讓我們還可以自定Hooks,自定義的Hooks可以在React自帶的Hooks之上抽離可以復(fù)用的操作。

React Redux 集成了自己定義的Hooks,這些Hooks可以讓你的React組件訂閱Redux store 和發(fā)送action

我們推薦使用React-Redux Hooks 作為React組件的默認(rèn)實(shí)現(xiàn)方式。
已經(jīng)存在的connect函數(shù)仍然可以使用并且會(huì)繼續(xù)提供支持,但是Hooks更加簡(jiǎn)單,與TypeScript使用效果會(huì)更好。

這些Hooks函數(shù)支持的最低版本 :7.1.0。

1.在React Redux應(yīng)用中使用Hooks#

使用 connect(),開(kāi)始你需要把整個(gè)應(yīng)用包裹在 <Provider> 組件中,確保store可以被整個(gè)組件樹(shù)訪(fǎng)問(wèn)到:

const store = createStore(rootReducer)

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
)

在這之后,你就可以引用所有的React Redux Hooks 并可以在函數(shù)組件中使用它們。

2.useSelector()#

const result: any =  useSelector(selector:  Function, equalityFn?:  Function)

通過(guò)selector可以讓你從Redux store state中獲取到數(shù)據(jù)。

INFO
selector應(yīng)該是純函數(shù),因?yàn)樗赡軙?huì)在任何時(shí)間點(diǎn)被執(zhí)行多次。

selector概念上基本相當(dāng)于 connect里的參數(shù) mapStateToProps 。當(dāng)函數(shù)組件渲染時(shí)selector就會(huì)執(zhí)行(除非selector本身相較于之前組件渲染時(shí)沒(méi)有變化,這時(shí)候Hook就會(huì)返回緩存的結(jié)果而不是重新運(yùn)行selector)。 useSelector()也會(huì)訂閱 Redux store,當(dāng)action執(zhí)行后會(huì)執(zhí)行selector。

然而,selector跟 useSelector()mapState還是有很多不同:

  • selector可以把任何值作為結(jié)果返回,不只是object。selector的返回值會(huì)被作為 useSelector()的返回值。
  • 當(dāng)一個(gè)action執(zhí)行后,useSelector()會(huì)把之前selector的值與當(dāng)前的值做比較。
  • selector 函數(shù)不會(huì)接收ownProps 參數(shù)。然而,props可以通過(guò)閉包使用(看下面的例子),或者通過(guò)柯里化的selector使用。
  • 當(dāng)使用memoizing selector時(shí)需要特別注意(看下面的例子)。
  • useSelector() 默認(rèn)使用嚴(yán)格的===做比較,不是通過(guò)淺比較(看下面的例子)。

INFO
有些在selector里使用props導(dǎo)致問(wèn)題的情況,參照本文注意事項(xiàng)章節(jié)獲取更多細(xì)節(jié)。

在一個(gè)函數(shù)組件中,你可能會(huì)調(diào)用多次 useSelector()。每次調(diào)用useSelector()都會(huì)對(duì)Redux store創(chuàng)建一個(gè)獨(dú)立的訂閱。因?yàn)镽eact Redux v7版本中React 的更新是批處理的,在同一個(gè)組件中一個(gè)action的分發(fā)本來(lái)應(yīng)該只會(huì)導(dǎo)致一次重新渲染,但卻會(huì)引起多個(gè)useSelector()返回新的值。

比較與更新#

當(dāng)一個(gè)函數(shù)組件渲染時(shí),提供的selector函數(shù)會(huì)執(zhí)行,結(jié)果也會(huì)通過(guò)useSelector()返回(如果是組件中的同一個(gè)函數(shù)的實(shí)例,則不會(huì)重新執(zhí)行selector,而是通過(guò)hook返回之前緩存的結(jié)果)。

當(dāng)一個(gè)aciton分發(fā)到Redux store后,useSelector()只會(huì)在selector結(jié)果與之前結(jié)果不同時(shí)才會(huì)強(qiáng)制重新渲染。v7.1.0-alpha.5版本,默認(rèn)的比較方式是嚴(yán)格的 ===強(qiáng)比較。這個(gè)跟connect()不同,connect()只是淺比較了mapState的結(jié)果來(lái)決定是否需要重新渲染。這可能會(huì)影響你如何使用useSelector()

使用mapState,所有的變量都會(huì)通過(guò)一個(gè)組合的object返回。這并不關(guān)心返回的object是否是新的值——connect()只比較object中的每個(gè)變量。

使用 useSelector(),返回一個(gè)新的object默認(rèn)肯定會(huì)重新渲染。如果你想從store中得到多個(gè)值,你可以:

  • 多次調(diào)用useSelector() ,每次返回一個(gè)變量的值。

  • 使用Reselect或者是類(lèi)似的庫(kù),創(chuàng)建一個(gè)memoizing的selector,可以通過(guò)一個(gè)object返回多個(gè)值。僅在一個(gè)值改變后就返回一個(gè)新的object。

  • 使用React-Redux 的淺比較函數(shù)作為useSelector()的參數(shù)equalityFn 。

  • useSelector()使用React-Redux中的淺比函數(shù)作為比較函數(shù),比如:

import  { shallowEqual, useSelector }  from  'react-redux'

// later

const selectedData =  useSelector(selectorReturningObject, shallowEqual)

這個(gè)可配置的比較函數(shù)也可以使用Lodash的 _.isEqual()或者Immutable.js中的比較能力。

useSelector 示例#

基本用法:

import React from 'react'
import { useSelector } from 'react-redux'

export const CounterComponent = () => {
  const counter = useSelector((state) => state.counter)
  return <div>{counter}</div>
}

通過(guò)閉包使用props取決于需要獲取什么數(shù)據(jù):

import React from  'react'
import  { useSelector }  from  'react-redux'

export const TodoListItem = (props)  =>  {
    const todo =  useSelector((state)  => state.todos[props.id])
    return  <div>{todo.text}</div>
}

使用 memoizing selectors#

如上面展示的,在內(nèi)聯(lián) selector中使用 useSelector時(shí),當(dāng)組件渲染完后會(huì)創(chuàng)建一個(gè)新的selector實(shí)例。這個(gè)實(shí)例會(huì) 一直有效直到不再持有任何state。 當(dāng)然,memoizing selector (比如 在 reselect中通過(guò) createSelector創(chuàng)建) 確實(shí)會(huì)有一個(gè)內(nèi)部的state,使用它們時(shí)必須注意。下面你會(huì)看到一些 memoizing selector的典型應(yīng)用場(chǎng)景。

當(dāng)selector只依賴(lài)于state時(shí),僅需要確保它是在組件外聲明的,這樣同一個(gè)selector就可以被每次渲染使用:

import React from 'react'
import { useSelector } from 'react-redux'
import { createSelector } from 'reselect'

const selectNumCompletedTodos = createSelector(
  (state) => state.todos,
  (todos) => todos.filter((todo) => todo.completed).length
)

export const CompletedTodosCounter = () => {
  const numCompletedTodos = useSelector(selectNumCompletedTodos)
  return <div>{numCompletedTodos}</div>
}

export const App = () => {
  return (
    <>
      <span>Number of completed todos:</span>
      <CompletedTodosCounter />
    </>
  )
}

如果selector依賴(lài)于組件的props,同一個(gè)是確定的。但是,只會(huì)被一個(gè)組件的一個(gè)實(shí)例使用:

import React from 'react'
import { useSelector } from 'react-redux'
import { createSelector } from 'reselect'

const selectCompletedTodosCount = createSelector(
  (state) => state.todos,
  (_, completed) => completed,
  (todos, completed) =>
    todos.filter((todo) => todo.completed === completed).length
)

export const CompletedTodosCount = ({ completed }) => {
  const matchingCount = useSelector((state) =>
    selectCompletedTodosCount(state, completed)
  )

  return <div>{matchingCount}</div>
}

export const App = () => {
  return (
    <>
      <span>Number of done todos:</span>
      <CompletedTodosCount completed={true} />
    </>
  )
}

但是,當(dāng)selector被多個(gè)組件實(shí)例使用并且依賴(lài)組件的props時(shí),你需要確定每一個(gè)組件的實(shí)例都能得到他自己的那個(gè)selector實(shí)例參見(jiàn)這里 ,獲取進(jìn)一步解釋?zhuān)瑸槭裁催@是必須的:

import React, { useMemo } from 'react'
import { useSelector } from 'react-redux'
import { createSelector } from 'reselect'

const makeSelectCompletedTodosCount = () =>
  createSelector(
    (state) => state.todos,
    (_, completed) => completed,
    (todos, completed) =>
      todos.filter((todo) => todo.completed === completed).length
  )

export const CompletedTodosCount = ({ completed }) => {
  const selectCompletedTodosCount = useMemo(makeSelectCompletedTodosCount, [])

  const matchingCount = useSelector((state) =>
    selectCompletedTodosCount(state, completed)
  )

  return <div>{matchingCount}</div>
}

export const App = () => {
  return (
    <>
      <span>Number of done todos:</span>
      <CompletedTodosCount completed={true} />
      <span>Number of unfinished todos:</span>
      <CompletedTodosCount completed={false} />
    </>
  )
}

3.useDispatch()#

const dispatch =  useDispatch()

useDispatch()dispatch返回了一個(gè)Redux store實(shí)例。你可以用它來(lái)dispatch action。

示例#

import React from 'react'
import { useDispatch } from 'react-redux'

export const CounterComponent = ({ value }) => {
  const dispatch = useDispatch()

  return (
    <div>
      <span>{value}</span>
      <button onClick={() => dispatch({ type: 'increment-counter' })}>
        Increment counter
      </button>
    </div>
  )
}

當(dāng)使用 dispatch向子組件傳遞回調(diào)時(shí),有時(shí)候你可能想通過(guò) useCallback來(lái)memoize它。子組件可以通過(guò)React.memo()等來(lái)優(yōu)化渲染操作,這樣可以避免子組件因回調(diào)函數(shù)(參數(shù)是個(gè)函數(shù))改變導(dǎo)致的不必要渲染。

import React, { useCallback } from 'react'
import { useDispatch } from 'react-redux'

export const CounterComponent = ({ value }) => {
  const dispatch = useDispatch()
  const incrementCounter = useCallback(
    () => dispatch({ type: 'increment-counter' }),
    [dispatch]
  )

  return (
    <div>
      <span>{value}</span>
      <MyIncrementButton onIncrement={incrementCounter} />
    </div>
  )
}

export const MyIncrementButton = React.memo(({ onIncrement }) => (
  <button onClick={onIncrement}>Increment counter</button>
))

INFO
只要通過(guò)<Provider>傳遞同一個(gè)store實(shí)例,dispatch 函數(shù)就是穩(wěn)定的。一般一個(gè)應(yīng)用中store實(shí)例不會(huì)改變。
當(dāng)然, React hook的檢測(cè)規(guī)則不會(huì)知道 dispatch是否應(yīng)該穩(wěn)定,并且會(huì)警告 dispatch變量應(yīng)該添加到useEffectuseCallback的依賴(lài)數(shù)組中。最簡(jiǎn)單的解決辦法如下:

export const Todos() = () => {
  const dispatch = useDispatch();

  useEffect(() => {
    dispatch(fetchTodos())
  // Safe to add dispatch to the dependencies array
  }, [dispatch])
}

4.useStore()#

const store =  useStore()

useStore返回了與傳遞給 <Provider>一樣的Redux store實(shí)例。

useStore不建議頻繁使用。建議把useSelector() 作為首選方式。

當(dāng)然,這個(gè)可能對(duì)個(gè)別需要使用store場(chǎng)景比較有用,比如代替 reducer。

示例#

import React from 'react'
import { useStore } from 'react-redux'

export const CounterComponent = ({ value }) => {
  const store = useStore()

  // EXAMPLE ONLY! Do not do this in a real app.
  // The component will not automatically update if the store state changes
  return <div>{store.getState()}</div>
}

5.自定義 context#

<Provider>組件可以讓你通過(guò)context屬性,指定一個(gè)自定義的context。如果你創(chuàng)建一個(gè)可復(fù)用的復(fù)雜組件這個(gè)設(shè)置會(huì)很有用,可以避免自定義應(yīng)用內(nèi)的Redux store沖突。

通過(guò)Hooks使用可替換的 context,可以使用hook創(chuàng)建函數(shù):

import React from 'react'
import {
  Provider,
  createStoreHook,
  createDispatchHook,
  createSelectorHook
} from 'react-redux'

const MyContext = React.createContext(null)

// Export your custom hooks if you wish to use them in other files.
export const useStore = createStoreHook(MyContext)
export const useDispatch = createDispatchHook(MyContext)
export const useSelector = createSelectorHook(MyContext)

const myStore = createStore(rootReducer)

export function MyProvider({ children }) {
  return (
    <Provider context={MyContext} store={myStore}>
      {children}
    </Provider>
  )
}

6.注意事項(xiàng)#

無(wú)用Props 和僵尸子節(jié)點(diǎn)#

INFO
React-Redux Hooks 從v7.1.0版本開(kāi)始可以穩(wěn)定使用了。我們推薦使用Hooks作為組件的默認(rèn)實(shí)現(xiàn)方式。但是也有些邊界用例問(wèn)題出現(xiàn),我們記錄了這些問(wèn)題以便大家能知道這些問(wèn)題。

React Redux在實(shí)現(xiàn)的時(shí)候最復(fù)雜的一個(gè)操作是需要保證mapStateToProps函數(shù)結(jié)構(gòu)類(lèi)似 (state, ownProps)這樣,每次props更新后都會(huì)調(diào)用。從版本4.0開(kāi)始就有反復(fù)出現(xiàn)了一些bug,比如:mapState函數(shù)因列表的item數(shù)據(jù)被刪除了而拋出異常。

從5.0版本開(kāi)始,React Redux試圖通過(guò)ownProps來(lái)確保一致性。在7.0版本,在connect()內(nèi)部通過(guò)自定義的Subscription來(lái)實(shí)現(xiàn),形成了嵌套調(diào)用。這樣確保了在組件樹(shù)子節(jié)點(diǎn)的組件只會(huì)在最近的鏈接的父節(jié)點(diǎn)更新后才會(huì)收到store更新的通知。但是這依賴(lài)于每個(gè)connect()實(shí)例重寫(xiě)部分內(nèi)部React context,用新的context支持自己獨(dú)有的Subscription來(lái)組建這個(gè)嵌套調(diào)用,使用心得context作為 <ReactReduxContext.Provider>的參數(shù)。

使用Hooks,不會(huì)渲染context provider,也就是不會(huì)有嵌套層級(jí)的訂閱。基于此,應(yīng)用如果使用Hook代替connect()可能會(huì)復(fù)現(xiàn)無(wú)用props和僵尸子節(jié)點(diǎn)問(wèn)題。

確切的說(shuō),無(wú)用props意味著:

  • selector函數(shù)依賴(lài)這個(gè)組件的props提取數(shù)據(jù)。
  • 父組件會(huì)重新渲染并且會(huì)以props的形式傳遞action的結(jié)果。
  • 組件的selector函數(shù),在組建接受到新的props重新渲染之前就執(zhí)行了。

Depending on what props were used and what the current store state is, this may result in incorrect data being returned from the selector, or even an error being thrown.
依賴(lài)于調(diào)用了什么樣的props跟什么樣的store state,這會(huì)導(dǎo)致selector返回不正確的數(shù)據(jù),甚至拋出異常。

僵尸子組件確切的說(shuō)是指如下情況:

  • 首次加載多個(gè)嵌套的關(guān)聯(lián)的組建會(huì)導(dǎo)致子組件在父組件之前訂閱store信息。
  • action會(huì)從store中返回刪除的數(shù)據(jù),比如todo item。
  • 父組件會(huì)停止渲染子組件。
  • 因?yàn)樽咏M件先訂閱了store信息,子組件的訂閱會(huì)在父組件停止渲染它之前運(yùn)行。當(dāng)讀取到store基于props的值時(shí),如果數(shù)據(jù)不存在了,并且獲取邏輯不嚴(yán)謹(jǐn),可能會(huì)導(dǎo)致拋出異常。

useSelector()就是用來(lái)解決以上問(wèn)題的:通過(guò)捕獲所有由于store更新(不是在渲染期間執(zhí)行)而導(dǎo)致selector運(yùn)行產(chǎn)生的異常。只要selector是一個(gè)純函數(shù)并且不依賴(lài)于selector拋出異常這個(gè)就會(huì)有效。

如果你傾向于自己處理這個(gè)問(wèn)題,下面是些可行的使用useSelector()時(shí)避免上述問(wèn)題的方案:

  • selector函數(shù)不要依賴(lài)props獲取數(shù)據(jù)。
  • 以防你的selector函數(shù)確實(shí)需要依賴(lài)于props,這些props可能會(huì)改變,或者你獲取的數(shù)據(jù)可能依賴(lài)于會(huì)不會(huì)刪除的item,selector函數(shù)要定義的保守一點(diǎn)。不要只是直接用state.todos[props.id].name,先獲取 state.todos[props.id],確保值存在再獲取todo.name。
  • 因?yàn)?code>connect在context provider中添加了必要的Subscription并且延時(shí)執(zhí)行子組件的訂閱操作直到關(guān)聯(lián)的組建重新渲染完。在關(guān)聯(lián)組件因同一個(gè)store更新而重新渲染時(shí),組件使用 useSelector 之前把關(guān)聯(lián)的組建放入組件樹(shù)可以避免上述問(wèn)題。

INFO
關(guān)于此場(chǎng)景更多的描述如下:

性能#

如早先提到的,使用默認(rèn)的useSelector()當(dāng)action執(zhí)行后運(yùn)行selector函數(shù)會(huì)對(duì)選中的值進(jìn)行比較,只有當(dāng)選中的值改變時(shí)組件才會(huì)重新渲染。但是不像connect(),useSelector()會(huì)因?yàn)楦附M件的重新渲染而而重新渲染子組件,即使子組件里的props沒(méi)有改變。

如果性能優(yōu)化是必須的,你需要考慮把你的函數(shù)組件包裹到 React.memo()中:

const CounterComponent = ({ name }) => {
  const counter = useSelector(state => state.counter)
  return (
    <div>
      {name}: {counter}
    </div>
  )
}

export const MemoizedCounterComponent = React.memo(CounterComponent)

7.Hooks 示例#

基于初始的alpha release,我們對(duì)Hooks的API進(jìn)行了精簡(jiǎn)。更關(guān)注較小的API原語(yǔ)。但是可能在你的應(yīng)用中你仍然想使用一些我們?cè)囘^(guò)的方式。下面的示例代碼可以直接復(fù)制并粘貼到你自己的代碼中。

方法: useActions()#

useActions()在之前的release分支中,但是基于Dan Abramov 的建議](https://github.com/reduxjs/react-redux/issues/1252#issuecomment-488160930)在v7.1.0-alpha.4版本移除掉了。這個(gè)建議是基于"binding action creators"在基于hook的使用場(chǎng)景下沒(méi)有用,并且會(huì)導(dǎo)致很多概念上的成本與句法的復(fù)雜性。

你可能更傾向于調(diào)用 useDispatch 在你的組件中獲取dispatch的實(shí)例。然后根據(jù)需要在回調(diào)或者effect中手動(dòng)調(diào)用dispatch(someActionCreator()) 。你的代碼中還可以使用Redux bindActionCreators 函數(shù)來(lái)綁定action creator,或者像const boundAddTodo = (text) => dispatch(addTodo(text))一樣綁定它們。

如果你確實(shí)喜歡使用Hooks,下面是可以復(fù)制粘貼的版本,支持通過(guò)action creator傳遞函數(shù)、數(shù)組或者
對(duì)象。

import { bindActionCreators } from 'redux'
import { useDispatch } from 'react-redux'
import { useMemo } from 'react'

export function useActions(actions, deps) {
  const dispatch = useDispatch()
  return useMemo(
    () => {
      if (Array.isArray(actions)) {
        return actions.map(a => bindActionCreators(a, dispatch))
      }
      return bindActionCreators(actions, dispatch)
    },
    deps ? [dispatch, ...deps] : [dispatch]
  )
}

方法: useShallowEqualSelector()#

import { useSelector, shallowEqual } from 'react-redux'

export function useShallowEqualSelector(selector) {
  return useSelector(selector, shallowEqual)
}

使用Hooks的額外注意事項(xiàng)#

當(dāng)考慮是否使用Hooks時(shí)有些架構(gòu)方面的問(wèn)題需要權(quán)衡。Mark Erikson在他發(fā)表的兩篇博客中總結(jié)的很好。 Thoughts on React Hooks, Redux, and Separation of ConcernsHooks, HOCs, and Tradeoffs。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,327評(píng)論 6 537
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,996評(píng)論 3 423
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 177,316評(píng)論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 63,406評(píng)論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,128評(píng)論 6 410
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 55,524評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,576評(píng)論 3 444
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,759評(píng)論 0 289
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,310評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,065評(píng)論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,249評(píng)論 1 371
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,821評(píng)論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,479評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,909評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 36,140評(píng)論 1 290
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,984評(píng)論 3 395
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,228評(píng)論 2 375

推薦閱讀更多精彩內(nèi)容