2017-12-30 63 views
0

Twitterクローンを作成しているが、ずっと簡単だとします。ここでは「ポスト」は、ポストの底にネイティブとリミックスとの反応で 'ツイート'のような機能を実装する方が良い

enter image description here

どのようなものか、私は3つのボタン、commentmessagelikeボタンが含まれている​​ものを、呼びたい何があります。の絵ですcommentボタンはユーザーが投稿にコメントできるようにし、messageボタンはユーザーに投稿の所有者にメッセージを送り、likeボタンはユーザーに投稿を好きにします。 likeボタンを押すと、ボタンの色が赤色に反転し、もう一度押すと灰色になります。

私がこれまで持っていることは、私は​​それは自身のstateのしている純粋な成分を、作る、ということである:commentCountlikedlikeCountlikedが、もしそうなら、このユーザーは、前にこの記事を気に入ったかどうかを示す真liked =、とのしたがって、likeボタンの色は最初赤色になり、ボタンを押すと、likedlikeCountのプロパティがそれに応じて変わります)。

私の問題は、ユーザーがポストを押したときに、私はこのように、彼らはポストのコメントを表示することができます別のページにそれらを取るでしょう、次のとおりです。 enter image description here

あなたはこのPost Contentページでそれを見ることができ、ユーザーは投稿を「好き」することもできます。ユーザーが投稿を好きにすると(likeボタンが赤くなります)、最初の画像のlikeボタンも更新されます。これをどのように実装すればよいですか?現在、私は​​に投稿のpostIdを投稿し、idが一致する場合は、likeボタンを更新して、投稿が好きになる度にreduxを使用しています。はい、それは、しかし、私はlikeボタンを押すたびに、色が変わるために約1秒かかります。私が望むのは、TwitterやFacebookのようなボタンの変更です。それ、どうやったら出来るの?

答えて

1

あなたはそれが意図的に使用されている方法を使用していないようです。

独自の状態のコンポーネントを持つ代わりに、redux store(https://redux.js.org/docs/basics/Store.html#store)で状態を管理する必要があります。

以下は、簡単な反応アプリケーションです。アプリには、「すべての投稿」と「特定の投稿」の2つのセクションがあります。 「すべての投稿」セクションには5つの投稿が表示され、それぞれに独自のボタンがあり、好きなように表示されます。 「特定の投稿」セクションでは、1つの投稿(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') 
 
);
<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>

関連する問題