preface
Not long after learning React, I felt that actual practice was the best way to test my learning level and deepen my understanding of React, so I made this small project to share with you.
Technology stack
- react
- react-router
- react-redux
- less
preview
Basic project construction
- Node development environment
- Installation dependency: YARN
- Start: YARN start
- When it comes to third-party API interfaces, you can apply for an AppKey by yourself at the interface address. After all, the number of requests is limited
Page structure
| | - react - kitchen project name - node_modules rely on package | - public | - SRC | | - components - API request data interface components directory | | - CardList card list components - the bottom of the Footer component | - | Header head components - NavLeft left navigation | - NavRight right tags | - | | - pages page config menu configuration - Collections collection page | - details on the Detail page. | | - Home front page - the Search Search page countless according to page | | - NoMatch -... Other navigation page | - redux redux data management action - types actions reducers store | - utils tools admin. Js page App. The outer structure js page routing common. Less page style Antd theme Settings Packjon. json Global configuration readme. md README fileCopy the code
Function implementation
The routing configuration
Project as a single page, the first step, of course, is to build the page route, because it is a menu item, routing or more, so here I put all the structure of the routing config file, under NavLeft navigation components to render the menu with the map function, avoids yourself to write one duplicate code, It is also convenient to add new navigation later.
Implementation code:
import React from 'react';
import { Menu} from 'antd';
import { NavLink } from 'react-router-dom'
import MenuConfig from '.. /.. /config/menuConfig'
const SubMenu = Menu.SubMenu;
export default class NavLeft extends React.Component {
componentWillMount() { const menuTreeNode = this.renderMenu(MenuConfig); This.setstate ({menuTreeNode})} // // menu renderMenu = (data) => {return data.map((item) => {
if (item.children) {
return (
<SubMenu title={item.title} key={item.key}>
{this.renderMenu(item.children)}
</SubMenu>
)
}
return <Menu.Item title={item.title} key={item.key}>
<NavLink to={item.key}>{item.title}</NavLink>
</Menu.Item>
})
}
render() {
return (
<div>
<Menu
onClick={this.handleClick}
>
{this.state.menuTreeNode}
</Menu>
</div>
)
}
}
Copy the code
CardList component encapsulation
The recipe preview uses ANTD’s Card component. When the page starts loading, it requests many sets of data from the API, and almost every navigation page uses the same list, so the whole list should be extracted and reused as a component.
Get the list of data from the interface first
getMenuAPIList = (keyword) => {
const num = 12
Axios
.jsonp({
url: `http://api.jisuapi.com/recipe/search?keyword=${keyword}&num=${num}&appkey=9d1f6ec2fd2463f7`
})
.then(res => {
if (res.status === '0') {
let cardList = this.renderCardList(res.result.list)
this.setState({
cardList: cardList
})
}
})
}
Copy the code
Call the data render list page. Note here that after rendering the preview image, click to enter the details page. How to get the current data to render the details page? Three ideas come to mind:
- Passes the data to the common parent component, which passes the data to the detail page component via props
- Through the way of routing, react to the router in v4 can link to pass parameters by means of the state to the next component, a component can through this. Props. The location. The state to get the data
- Use Redux to manage data
I’m going to do it the second way
RenderCardList = (data) => {return data.map((item) => {
return (
<NavLink key={item.id} to={{
pathname: `/common/detail/${item.id}`,
state: item
}} >
<Card
hoverable
className="card"
cover={<img alt="example" src={item.pic} />}
onClick={this.openMenuDetail}
id={item.id}
>
<Meta
style={{ whiteSpace: 'nowrap' }}
title={item.name}
description={item.tag}
/>
</Card>
</NavLink>
)
})
}
Copy the code
The search function
As mentioned above, link can be used to carry parameters for communication between components. For the search function here, REdux is used for data transmission between components, that is, the value of the input box is passed to the search page component, so that it can request data to THE API after it gets the value.
- CreateStore is used to generate a store container that takes a pure function reducer as an argument to return a new store
const store = createStore(reducer)
- Reducer accepts the Action and the current State as parameters and returns a new State
export function reducer(state = 1, action) {
switch (action.type) {
case TRANSMIT:
return action.data
default:
return state
}
}
Copy the code
- There are an infinite number of values in the input field, that is, there are an infinite number of Actions sent by the user. You can use an Action Creator function to generate Actions
export const transmit = (data) => {
return { type: TRANSMIT, data: data }
}
Copy the code
- Here we introduce react-redux to wrap the root component with the Provider. All child components get state by default
ReactDOM.render(<Provider store={store} ><App /></Provider>, document.getElementById('root'));
Copy the code
- Connect the UI components Header and Search with connect(). The connect method takes two parameters: mapStateToProps and mapDispatchToProps. MapStateToProps subscribes to store, and state updates are performed automatically. The Search component can get the current state of this.props. Keyword, and mapDispatchToProps as an object. Each key inside is treated as an Action Creator
export default connect(
state => ({keyword: state}),
{transmit}
)(Header)
export default connect(
state => ({keyword : state}),
{}
)(Search)
Copy the code
Since I don’t know much about Redux, the process here is a bit complicated. Simply share my understanding. You can go to see Teacher Ruan Yifeng’s Redux tutorial, which is very detailed
Collection function
Favorites function is mainly used to achieve localStorage, the main idea is: When clicking “Favorites”, check whether the data exists in localStorage. If it does not, convert the data into a string and save it in localStorage. Localstorage.setitem (), if localstorage.removeItem() exists, unbookmark it
handleCollect = () => {
let starColor = this.state.starColor
let isCollect = this.state.isCollect
const menu = JSON.stringify(this.state.menu)
const menuName = this.state.menu.name
if (isCollect === false) {
starColor = '#FDDA04'isCollect = ! isCollectlocalStorage.setItem(menuName, menu)
} else {
starColor = '#52c41a'isCollect = ! isCollectlocalStorage.removeItem(menuName)
}
this.setState({
starColor,
isCollect
})
message.success((isCollect ? 'Collected successfully' : 'Uncollect'), 1)}Copy the code
Project on pit
antd Input.Search
Click Search to redirect the route because ANTD encapsulates the input field and button. If you wrap Search with link, the route will jump directly without input text
Solution: Don’t use input. Search, directly use Input Input box +Button Button, get Input value in Button click event, and then use Link to wrap Button for route jump. This is the way I think of, if there is a better solution, also welcome friends to propose ~
Search page re-rendering
Act-redux: componentWillMount: componentWillMount: componentWillMount: componentWillMount: componentWillMount: function.keyword Searches for rendering the page after using the hook function is componentWillReceiveProps, this time parameters passed is nextProps keyword, rather than this. Props. The keyword
React Renders HTML code for example<br />
Cannot display correctly
React JSX anti-injection attack XSS renders all HTML code in braces as strings instead of HTML code
Solution: Use the tag attribute dangerouslySetInnerHTML
<div dangerouslySetInnerHTML={{__html: code}}></div>
Copy the code
conclusion
Item portal
When I was writing a project, I encountered many small problems, which were solved one by one by slowly checking the documents. Continuous thinking and solving problems is also a part of growth.
Of course, the project still needs to be improved in many areas, if there are mistakes or deficiencies, I also hope you can give me some advice
Last but not least, shamelessly beg for a STAR😋