project link: https://chuanshuoge1.github.io/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