K.W*_*.Wu 2 react-native redux
假设我正在编写一个Twitter克隆,但要简单得多。这是一张“帖子”的图片
在帖子的底部,有一个我称之为的Social Bar东西,其中包含3个按钮comment,message和like按钮。comment按钮可让用户对帖子发表评论,message按钮可让用户向帖子所有者发送消息,like按钮可让用户“喜欢”帖子。按下like按钮时,按钮的颜色将变为红色,再次按下将使其变为灰色。
我至今是,我做Social Bar一个纯粹的成分,它有它自己state:commentCount,liked,likeCount(liked表示该用户是否喜欢这个职位之前,如果是这样,liked= TRUE,因此,颜色like按钮,最初将红,在按下按钮,liked和likeCount特性将相应改变)。
我的问题是,当用户按下帖子时,我会将他们带到另一个页面,他们可以在其中查看帖子中的评论,如下所示:

您可以在此Post Content页面中看到,用户也可以“喜欢”该帖子。如果用户决定“喜欢”该帖子(like按钮将为红色),则like第一张图片中的按钮也应进行更新。我应该如何实施呢?目前,我正在使用redux,只要我“喜欢”帖子,就将帖子的“广播” postId到every Social Bar,如果id匹配,则更新like按钮。是的,它可以工作,但是,每当我按下like按钮时,颜色更改大约需要1秒钟。我想要的是按钮立即更改,例如Twitter和Facebook。我怎么做?
似乎您没有按照预期的方式使用redux。
与其让组件具有自己的状态,不如使用redux store(https://redux.js.org/docs/basics/Store.html#store)管理状态。
您可以在下面找到一个简单的react应用程序。应用程序中有2个部分:“所有帖子”和“特定帖子”。在“所有帖子”部分,您可以看到5个帖子,每个帖子都有自己的“喜欢”按钮和“喜欢”计数器。在“特定帖子”部分中,它仅呈现一个帖子(帖子#2)。
查看您在第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')
);Run Code Online (Sandbox Code Playgroud)
<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>Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2051 次 |
| 最近记录: |