使用react native和redux

时间:2017-12-30 23:11:38

标签: react-native redux

假设我正在编写Twitter克隆但更简单。这是“帖子”看起来像什么的图片

enter image description here

在帖子的底部,有一个我称之为Social Bar的内容,其中包含3个按钮,commentmessagelike按钮。 comment按钮可让用户对帖子发表评论,message按钮可让用户向帖子的所有者发送消息,like按钮可让用户“喜欢”帖子。按下like按钮后,按钮的颜色将变为红色,再次按下该按钮会使其再次变为灰色。

到目前为止,我将Social Bar设为一个纯组件,它有自己的statecommentCountlikedlikeCountliked表示此用户之前是否喜欢此帖子,如果是,liked = true,因此,按下按钮like按钮的颜色最初为红色,{{ 1}}和liked属性会相应更改。

我的问题是,当用户按下帖子时,我会将他们带到另一个页面,在那里他们可以查看帖子上的评论,如下所示: enter image description here

您可以在此likeCount页面中看到用户也可以“喜欢”该帖子。如果用户决定“喜欢”帖子(Post Content按钮为红色),则第一张图片中的like按钮也应该更新。我该如何实现呢?目前,我正在使用like,每当我想要发布帖子时,我都会向每个redux广播“帖子的postId,如果Social Bar匹配,然后更新id按钮。是的,它可以工作,但是,每次按like按钮,颜色需要大约1秒钟才能更改。我想要的是立即改变按钮,如Twitter和Facebook。我该怎么做?

1 个答案:

答案 0 :(得分:6)

您似乎没有按照预期的方式使用redux。

您应该使用redux store(https://redux.js.org/docs/basics/Store.html#store)管理状态,而不是让组件具有自己的状态。

下面你可以找到一个简单的反应应用程序。应用程序中有2个部分:"所有帖子"和"特定职位"。在"所有帖子"部分你可以看到5个帖子,每个帖子都有自己喜欢的按钮,喜欢计数器。在"特定帖子"它只呈现一个帖子(帖子#2)。

当您点击&#34时,查看所有内容是如何保持同步的。在帖子#2上,无论你点击哪一部分(所有帖子/特定帖子)。



const createStore = window.Redux.createStore;
const combineReducers = window.Redux.combineReducers;
const connect = window.ReactRedux.connect;
const Provider = window.ReactRedux.Provider;

const postsData = [
  { id: 1, likes: 0 },
  { id: 2, likes: 1 },
  { id: 3, likes: 0 },
  { id: 4, likes: 3 },
  { id: 5, likes: 2 },
];

// First, we're defining the initial state
const initialState = {
  posts: postsData,
  postsLikeCounters: postsData.reduce((out, post) => {
    return {
      ...out,
      [post.id]: post.likes
    };
  }, {})
};


// Then we're defining our reducers. Here I have 3 reducers:
// posts, postsLikes and postsLikeCounters
// Obviously you may want to use other data structures
function posts(state=posts, action) {
  return state;
}

function postsLikes(state={}, action) {
  switch (action.type) {
    case 'LIKE_POST':
      return {
        ...state,
        [action.post.id]: true
      };
    case 'UNLIKE_POST':
      return {
        ...state,
        [action.post.id]: false
      };
    default:
      return state;
  }
}

function postsLikeCounters(state={}, action) {
  let value;

  switch (action.type) {
    case 'LIKE_POST':
      value = state[action.post.id] || 0;
      
      return {
        ...state,
        [action.post.id]: value + 1
      };
    case 'UNLIKE_POST':
      value = state[action.post.id] || 0;

      return {
        ...state,
        [action.post.id]: Math.max(value - 1, 0)
      };
    default:
      return state;
  }
}

// Now we're combining all reducers into a single rootReducer
const rootReducer = combineReducers({
  posts,
  postsLikes,
  postsLikeCounters
});

// With rootReducer and the initialState we're ready to create our store
// To put it simple - store is a single place to keep the whole application state (instead of keeping it in specific components)
const store = createStore(rootReducer, initialState);


// Now we're going to define our components
const Post = (props) => (
  <div style={ {border:'1px solid #000', margin: 5} }>
    <strong>Post #{props.post.id}</strong>
    {props.liked ? (
      <button onClick={()=>props.onUnlike(props.post)}>
        Unlike
      </button>
    ) : (
      <button onClick={()=>props.onLike(props.post)}>
        Like
      </button>
    )}
    <span>({props.likes} likes)</span>
  </div>
)

const Posts = (props) => (
  <div>
    { props.posts.map(post => (
      <Post 
        key={post.id}
        post={post}
        likes={props.postsLikeCounters[post.id]}
        liked={props.postsLikes[post.id]}
        onLike={props.onLike}
        onUnlike={props.onUnlike} />
    ) ) }
  </div>
);


// Define onLike and onUnlike actions
const onLike = (post) => ({ type: 'LIKE_POST', post });
const onUnlike = (post) => ({ type: 'UNLIKE_POST', post });


// Create components that uses redux's store to manage state
const PostsWithLikes = connect(
  function(state){
    return {
      posts: state.posts,
      postsLikes: state.postsLikes,
      postsLikeCounters: state.postsLikeCounters
    };
  },
  {
    onLike,
    onUnlike
  }
)(Posts)

const SpecificPost = connect(
  function(state, ownProps){
    const id = ownProps.id;
    const post = state.posts.find(post => post.id === id);

    return {
      post: post,
      liked: state.postsLikes[id],
      likes: state.postsLikeCounters[id]
    };
  },
  {
    onLike,
    onUnlike
  }
)(Post);


// And we're ready to put it all together:
const App = (
  <Provider store={store}>
    <div>
      <h1>all posts:</h1>
      <PostsWithLikes />
      <div>
        <h2>specific post:</h2>
        <SpecificPost id={2} />
      </div>
    </div>
  </Provider>
);

ReactDOM.render(
  App,
  document.getElementById('rootElement')
);
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.7.2/redux.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/5.0.6/react-redux.js"></script>

<div id="rootElement"></div>
&#13;
&#13;
&#13;