Sunday, 20 May 2018

react-redux


page loaded from github

click load tweets, add, update tweet

observe state change in log


input box update user

project src folder

reducer folder

action folder

----------------------------------------------------------------------------------
//src folder
//index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

import App1 from "./appStart";
import registerServiceWorker from './registerServiceWorker';
import { Provider } from "react-redux";
import store from "./store";

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

registerServiceWorker();

-------------------------------------------------------------------------------------

//appstart.js

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { fetchUser, setUserName, setUserAge } from './actions/userActions';
import { fetchTweets, addTweet, updateTweet } from './actions/tweetsActions';

class App1 extends Component {

    componentWillMount() {
        this.props.dispatch(fetchUser());
    }

    handle_loadTweet() {
        this.props.dispatch(fetchTweets());
    }

    handle_addTweet(id) {
        this.props.dispatch(addTweet(id,"new title"));
    }

    handle_updateTweet(id) {
        this.props.dispatch(updateTweet(id, "updated title"));
    }

    handle_updateUserName(e) {
        if (e.keyCode === 13) {
            this.props.dispatch(setUserName(e.target.value));
        }
    }

    handle_setUserAge(e) {
        if (e.keyCode === 13) {
            this.props.dispatch(setUserAge(parseInt( e.target.value)));
        }
    }

    render() {

        console.log(this.props.user);
        console.log("user fetched", this.props.userFetched);
        console.log("tweet fetched", this.props.tweetFetched);
        console.log("tweets[]", this.props.tweets);

        const { user, tweets } = this.props;        

        const load_tweet_button = tweets.length ? <span /> :
            <button onClick={() => this.handle_loadTweet()}>load tweets</button>;

        const mappedTweets = tweets.map((tweet, index) =>
            <li key={index}>{tweet.title}</li>
        ).slice(tweets.length-10, tweets.length);

        return (
            <div>
                redux
                <p>{user.name} {this.props.user.age}</p>
                <input type="text" onKeyDown={(e) => this.handle_updateUserName(e)} defaultValue="update name press enter" />
                <input type="number" onKeyDown={(e) => this.handle_setUserAge(e)} defaultValue={20} />
                <br />
                {load_tweet_button}
                <button onClick={() => this.handle_addTweet(tweets.length + 1)}>add tweet</button>
                <button onClick={() => this.handle_updateTweet(tweets.length)}>update last tweet</button>
                <ul>{mappedTweets}</ul>
            </div>
        );
    }
}

export default connect(
    (store) => {
        return {
            user: store.user.user,
            userFetched: store.user.fetched,
            tweetFetched: store.tweets.fetched,
            tweets: store.tweets.tweets,
        };
    }
)(App1);

------------------------------------------------------------------

//store.js

import { applyMiddleware, createStore } from 'redux';
import logger from 'redux-logger';
import thunk from 'redux-thunk';
import promiseMiddleware from 'redux-promise-middleware';

import reducer from "./reducers";

const middleware = applyMiddleware(promiseMiddleware(), thunk, logger);

export default createStore(reducer, middleware);

---------------------------------------------------------------

//action folder
//tweetAction.js

import axios from 'axios';

export function fetchTweets() {
    return {
        type: "fetch_tweet",
        payload: axios.get("https://jsonplaceholder.typicode.com/posts")
    }
}

export function addTweet(id, text) {
    return {
        type: "add_tweet",
        payload:{
            id,
            text,
        },
    }
}

export function updateTweet(id, text) {
    return {
        type: "update_tweet",
        payload: {
            id,
            text,
        },
    }
}

---------------------------------------------------------------------------

//userActions.js

export function fetchUser() {
    return {
        type: "fetch_user_FULFILLED",
        payload: {
            name: "will",
            age:35,
        }
    }
}

export function setUserName(name) {
    return {
        type: "set_user_name",
        payload:name,
    }
}

export function setUserAge(age) {
    return {
        type: "set_user_age",
        payload:age,
    }
}

-------------------------------------------------------

//reducer folder
//index.js

import { combineReducers } from 'redux';

import tweets from "./tweetsReducer";
import user from "./userReducer";

export default combineReducers(
    {
        tweets,
        user,
    })

----------------------------------------------

//tweetReducer

export default function reducer(
    state = {
        tweets: [],
        fetching: false,
        fetched: false,
        error: null,
    },
    action
) {
    switch (action.type) {
        case "fetch_tweet_PENDING": {
            return { ...state, fetching: true }
            break;
        }
        case "fetch_tweet_FULFILLED": {
            return {
                ...state,
                fetching: false,
                fetched: true,
                tweets: action.payload.data,
            }
            break;
        }
        case "fetch_tweet_REJECTED": {
            return {
                ...state,
                fetching: false,
                error: action.payload,
            }
            break;
        }

        case "add_tweet": {
            const newTweets = [...state.tweets];
            const added_tweet = { "id": action.payload.id, "title": action.payload.text };
            newTweets.push(added_tweet);

            return {
                ...state,
                tweets: newTweets,
            }
        }

        case "update_tweet": {
            const { id, text } = action.payload;
            const newTweets = [...state.tweets];
            const tweetToUpdate = newTweets.findIndex(tweet => tweet.id === id);
            newTweets[tweetToUpdate].title = text;

            return {
                ...state,
                tweets: newTweets,
            }
        }

        case "delete_tweet": {
            return {
                ...state,
                tweets: state.tweets.filter(tweet => tweet.id !== action.payload),
            }
        }
    }
    return state;
}

------------------------------------------------------------------

//userReducer

export default function reducer(
    state = {
        user: {
            id: null,
            name: null,
            age:null,
        },
        fetching: false,
        fetched: false,
        error: null,
    },
    action
) {
    switch (action.type) {
        case "fetch_user_PENDING": {
            return { ...state, fetching: true }
            break;
        }
        case "fetch_user_FULFILLED": {
            return {
                ...state,
                fetching: false,
                fetched: true,
                user: action.payload,
            }
            break;
        }
        case "fetch_user_REJECTED": {
            return {
                ...state,
                fetching: false,
                error: action.payload,
            }
            break;
        }
        case "set_user_name": {

            return {
                ...state,
                user: { ...state.user, name: action.payload },
            }
        }

        case "set_user_age": {

            return {
                ...state,
                user: { ...state.user, age: action.payload },
            }
        }
    }
    return state;
}

No comments:

Post a Comment