Ahri – from the land

In Day32, I will summarize my experience of writing a music player and show you how to quickly write a React + Redux project, using the music player search function as an example.

The online demo

Program source code

Functional analysis:

Train of thought

1. Click the search button, pass the value of the search as an argument to the function that gets the search results, and pass the component’s Dispatch method to the function via Connect.

2. Use fetch to obtain the search result and send the processed search result as the value of the action object to the reducer.

3. The Reducer function updates the search results to the store based on the action

4. The search results display component renders data according to the value of store

The project framework

1. Create a basic React project framework using create-React-app, the official react scaffolding

2. Modify the index entry file in SRC

Modified code

import React from 'react'; import ReactDOM from 'react-dom'; import {Router,Route,IndexRoute,hashHistory} from 'react-router'; import { Provider } from 'react-redux'; / / the introduction of the Provider will store data sharing to child components import 'bootstrap/dist/CSS/bootstrap CSS'; import './index.css'; import finalCreateStore from './store/configureStore' ; Reduce reducers from './reducers' // Reduce reducers collection // Introduce sub-components (custom) import App from './App'; // import Lrc from './Lrc'; Import Demo from './Demo'; // Import registerServiceWorker from './registerServiceWorker'; const store = finalCreateStore(reducer); class Nav extends React.Component{ render(){ return( <Provider store={store}> <div> <App/> {this.props.children} </div> </Provider>)}} reactdom.render ((<Router history={hashHistory}> <Route path="/" Component ={Nav}> // home <IndexRoute <Route path="/ LRC "Component ={LRC}/> </Route> </Router>), document.getelementById ('root')); registerServiceWorker();Copy the code

3. Add the configureStore file introduced in the index file, which is used to enhance the store generation method so that we can see every change in the store

Create a new folder store in SRC and place configureStore.js in the store folder

ConfigureStore. Js code

Import thunk from 'redux-thunk' // redux-thunk supports dispatch function, Import createLogger from 'redux-Logger' import {createStore, applyMiddleware, Compose} from 'redux' // import DevTools from '.. Const loggerMiddleware = createLogger const Middleware = [thunk, LoggerMiddleware] // Use compose to augment store, The store uses const finalCreateStore = compose with applyMiddleware and Redux-devtools (... middleware), //DevTools.instrument(), )(createStore) export default finalCreateStoreCopy the code

4. Supplement the reducers introduced in index file. This folder contains count.js and index.js files. Index.js for merging reducers (I only have one reducer so it doesn’t work)

Create a new folder reducers in SRC and place count.js and index.js in that directory

Count. Js code

// reducers/count.js import { GETSUCCESS } from '.. /constants' // Introducing action type constant name // Initializing state const initialState = {data: [{id: 209326, img: "http://p1.music.126.net/BZNpKSKkPTTv5ZnxdYAdUQ==/5850501371402948.jpg", LRC England: ", "name:" "the meaning of travel, // Enter export default function update(state = initialState, Switch (action.type) {case GETSUCCESS: return object.assign ({}, state, {data: action.data }) default: return state } }Copy the code

The index. The js code

// reducers/index.js import {combineReducers} from 'redux' // Merge combineReducers import update from combineReducers Reducer export Default combineReducers({update,})Copy the code

5. Supplement the constantes file introduced in reducers/count.js, which is used to define action type constant names

Create constantes.js in the SRC directory

Constantes. Js code

// export const GETSUCCESS = 'GETSUCCESS'Copy the code

6. Create a Actions folder in the SRC directory. This folder contains a count.js file that processes requests from the component and passes the actions to the Reducer function

Count. Js code

import { GETSUCCESS } from '.. /constants' // Importing action type name constant import 'WHATwG-fetch' // Fetch can be imported for Ajax // This method returns an action object export const getSuccess = (json) => { return { type: GETSUCCESS, data } }Copy the code

The react-Router3.0.0, redux, react-redux, bootstarp, redux-thunk, and redux-Logger dependencies are all set up and ready to write

Function implementation

1. Write components

Search box: Search for the desired song

Component code

import React, { Component } from 'react'; import {Link} from 'react-router'; import { connect } from 'react-redux'; // introduce connect import {fetchPostsIfNeeded} from './actions/count' // introduce a function in count that is used to obtain song information import './ app.css '; Class App extends Component {constructor(props) {super(props) this. State = {value:' Chen Chen ', class: 'collapse navbar-collapse', class1: 'navbar-form navbar-right', liked: HandleChange =(event)=> {this.setState({value: event.target.value}); } hand=(event)=> {if(this.state. Liked) this.setState({liked: false,class:'',class1:'nav navbar-nav search'}); else this.setState({liked: true,class:'collapse navbar-collapse',class1:'navbar-form navbar-right'}); } render() { const { fetchPostsIfNeeded } = this.props; var value = this.state.value; return ( <nav className="navbar navbar-default App"> <div className="container-fluid"> <div className="navbar-header"> <a className="navbar-brand" href=""> <img SRC ='favicon.ico' className=" app-logo "Alt ="logo" /> <button className="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse" onClick={this.hand}> <span className="icon-bar"></span> <span className="icon-bar"></span> <span className="icon-bar"></span> </button> </div> <div  className={this.state.class}> <ul className="nav navbar-nav"> <li className="dropdown"><Link to="/" onClick={this.hand}>Demo</Link></li> <li className="dropdown"><Link to="/lrc" onClick={this.hand}>Lrc</Link></li> </ul> <div className={this.state.class1}> <span><input type="text" value={value} onChange={this.handleChange} /></span> <Link To ="/"><button onClick={() => fetchPostsIfNeeded(this.state-value)}><span onClick={this.hand}> </div> </div> </div> <div>{this.props.children}</div> </nav> ); } // Get data from store const getList = state => {return {lists: State.update. data}} // Bind data data to the this.props of the component, Export default Connect (getList, {fetchPostsIfNeeded})(App)Copy the code

Song information display card: show the song cover, song title, artist name, song duration, and play button.

Component code

    class Card extends React.Component{
	constructor(props) {
    super(props);
    this.state = {};
	}
    render(){
        return(
				<div className="col-sm-3 col-xs-6 card" >
					<div className="card_box">
					  <Link to="/lrc"><img src={this.props.img} alt={this.props.name} /></Link>
					  <div  className="card_content">
						  <p>{this.props.singer}</p>
						  <Link to="/lrc"><h3>{this.props.name}</h3></Link>
						  <div>
						  <Link to="/lrc"><span className="glyphicon glyphicon-play" ></span></Link>
							<span className="time">{this.props.time}</span>
							<span className="glyphicon glyphicon-share"></span>
						  </div>
					  </div>
				  	</div>
				</div>
        )
    }
}
    Copy the code

Card container: A large div that holds the card and provides information to the card

Implementation approach

This container is going to feed the card with the song information, which needs to be taken from the Store.

Component code

import React from 'react'; import Card from './Card'; import { connect } from 'react-redux'; Constructor (props) {super(props) this.state = {}} render() {const {}} render() {const {  data } = this.props; return ( <div className="box"> {data.map((key,index) => <Card key={index.toString()} url={key.url} name={key.name} time={key.time} lrc={key.lrc} img={key.img} id={key.id} singer={key.singer} /> )} </div> ); } // getData from store const getData = state => {return {data: // Pass the data to the component.props export default connect(getData)(Demo)Copy the code

2. Define the action variable name of the requested search song in constants.js

export const GETSUCCESS = 'GETSUCCESS'Copy the code

3. Add the action type name constant to actions/count.js and write the fetchPostsIfNeeded function for the action and search box

Count. Js code

import { GETSUCCESS } from '.. /constants' // Importing action type name constant import 'WHATwG-fetch' // We can import fetch for Ajax // The method here returns an Action object // Handling song information export const getSuccess = (json) => { return { type: GETSUCCESS, data}} / / song information function fetchPosts search method (keyword) {/ / server address var url = 'http://youxinyu.me:3000/search? keywords='+keyword; return dispatch => { return fetch(url, { method: 'GET', mode: 'cors', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, }) .then((res) => { console.log(res.status); return res.json() }) .then((data) => { var action = getSuccess(data); Dispatch (action)}). Catch ((e) => {console.log(e.message)})}} export function fetchPostsIfNeeded(keyword) { return (dispatch, getState) => { return dispatch(fetchPosts(keyword)) } }Copy the code

4. Initialize state in the reducers/count.js file, give it a variable data to store the data we searched, and update the value of state in the update function

Count. Js code

// reducers/count.js import { GETSUCCESS } from '.. /constants' // Introducing action type constant name // Initializing state const initialState = {data: [{id: 209326, img: "http://p1.music.126.net/BZNpKSKkPTTv5ZnxdYAdUQ==/5850501371402948.jpg", LRC England: ", "name:" "the meaning of travel, // Enter export default function update(state = initialState, Switch (action.type) {case GETSUCCESS: return object.assign ({}, state, {data: action.data }) default: return state } }Copy the code

Ok, here, we write the search function, and then add the function to do a function to achieve these steps can be ~

See the full code and examples

See the code pointhere~

Play a game pointhere~

End