2017-12-30 30 views
0

Angenommen, ich schreibe einen Twitter-Klon, aber viel einfacher. Hier ist ein Bild von dem, was ein ‚post‘ sieht aus wieBessere Möglichkeit, 'wie Tweet'-Funktionalität mit reagieren native und redux

enter image description here

Im Boden eines Post, gibt es ein, was ich Social Bar Sache nennen würde, die drei Schaltflächen enthält, comment, message und like Taste. comment Schaltfläche können Benutzer Kommentare zu dem Beitrag, message Schaltfläche können Benutzer Nachricht den Besitzer des Beitrags, und like Schaltfläche lässt Benutzer "wie" der Beitrag. Wenn Sie die Taste like drücken, wird die Farbe der Schaltfläche zu rot, durch erneutes Drücken wird sie wieder grau.

Was ich habe, so weit ist, dass ich Social Bar eine reine Komponente machen, die seine eigenen state hat: commentCount, liked, likeCount (liked zeigt an, ob dieser Benutzer diesen Beitrag vor gemocht hat, wenn ja, liked = true, und Daher ist die Farbe der like Schaltfläche zunächst rot, wenn Sie auf die Schaltfläche drücken, ändern sich die Eigenschaften liked und likeCount entsprechend).

Mein Problem ist, wenn Benutzer die Post drücken, ich sie auf eine andere Seite nehmen, wo sie die Kommentare zu dem Beitrag sehen können wie folgt aus: enter image description here

Sie, dass in dieser Post Content Seite sehen können, Benutzer können den Post auch "mögen". Wenn Benutzer sich entscheiden, den Beitrag zu "mögen" (like Button wird rot), dann sollte der like Button im ersten Bild auch aktualisiert werden. Wie soll ich das umsetzen? Zur Zeit verwende ich redux, wenn ich einen Beitrag "mag", sende ich die postId des Beitrags an jede Social Bar, und wenn die id übereinstimmt, dann aktualisieren Sie die like Schaltfläche. Ja, es funktioniert, aber jedes Mal, wenn ich die like Taste drücke, dauert es etwa 1 Sekunde, bis sich die Farbe ändert. Was ich will ist für den Button die Änderung sofort, wie Twitter und Facebook. Wie mache ich das?

Antwort

1

Es scheint, dass Sie Redux nicht so verwenden, wie es beabsichtigt war.

Anstatt Komponenten mit einem eigenen Status zu haben, sollten Sie den Status mit einem Redux-Speicher verwalten (https://redux.js.org/docs/basics/Store.html#store).

Unten finden Sie eine einfache Reaktion Anwendung. Es gibt 2 Abschnitte in der App: "Alle Posts" und "Spezifischer Post". In der Rubrik "Alle Posts" können Sie 5 Posts sehen, jede mit einem eigenen Like Button und Likes Counter. Im Bereich "specific post" wird nur ein einziger Beitrag (Post # 2) gerendert.

Sehen Sie, wie alles synchron bleibt, wenn Sie in Post # 2 auf "Gefällt mir" klicken, egal in welchem ​​Abschnitt Sie klicken (alle Posts/spezifischen Posts).

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>

Verwandte Themen