函数式组件
在16.8版本之前函数式组件无法写状态所以一般只能用class组件成本比较高代码嵌套比较深,并且钩子函数(生命周期相对来说过于复杂)在16.8之后出了函数式组件的状态后,很好的解决了这些弊端。
在之前版本中函数式组件是不支持状态的为了让函数式组件更好的支持状态,可以利用useState
const [name,setName] = useState("Riven")
主要利用这个useState的方法 也是一个数组它有个值一个是Riven,另一个是修改这个状态的方法f()你可以打印一下自己查看console.log(useState(“Riven”)) 如上代码就是将这个状态和这个修改状态的方法给解构出来这样就可以访问到状态,并且进行修改了
// rcc => react component class
// rfc => react component function
import React,{useState} from 'react'
//利用useState让函数式组件支持状态
function App(){
console.log(useState("Riven"));
//不支持状态
const [name,setName] = useState("Riven")
const [age,setAge] = useState(25)
return(
app----{name}---{age}
)
}
export default App
以上就是函数式组件的基本写法了你肯定有许多问题?函数式组件的生命周期呢?函数式组件的传值呢通信呢?没有类组件的写法这些应该怎么写呢?
请随我继续往后看
首先怎么获取input框中的value值呢?
这里我们有两种方法和类组件差不多
import React,{useState} from 'react'
function App(){
const [text, setText] = useState("")
return(
{
// console.log(ev.target)
setText(ev.target.value)
}} />
)
}
export default App
这种方法较为复杂需要利用useRef
import React,{useState,useRef} from 'react'
const mytext = useRef(null)
{
// console.log(ev.target)
setText(ev.target.value)
}} ref={mytext} />
访问的时候可以直接通过mytext.current.value得到value值
import React,{useState,useRef} from 'react'
function App(){
const [text, setText] = useState("")
const mytext = useRef(null)
return(
{
// console.log(ev.target)
setText(ev.target.value)
}} ref={mytext} />
)
}
export default App
需要注意学习的地方
input框value值获取
怎么让进行添加
怎么让添加完成后输入框的value值清空
怎么进行删除
import React,{useState,useRef} from 'react'
function App(){
const [text, setText] = useState("")
const [list,setList] = useState(["111","222","333"])
const mytext = useRef(null)
//删除函数只是想写在外面
const handledelclick = (index)=>{
var newlist = [...list]
newlist.splice(index,1)
setList(newlist)
}
return(
{
// console.log(ev.target)
setText(ev.target.value)
}} ref={mytext} value={text} />
{
list.map((item,index)=>
{item}
)
}
)
}
export default App
在函数式组件中我们没有生命周期useEffect类似生命周期但不是生命周期
我们把数据请求放在函数组件的哪里呢?
首先需要知道useEffect接收两个参数,第一个是处理函数,第二是依赖
第一个参数相当于一旦创建就会执行。
如果第二个参数传入的依赖状态改变也会自动执行
如果第二个参数传入的依赖状态为空就相当于值会走一次
如果不传任何状态改变都会触发第一个处理函数的执行
return 出来的这个函数只有销毁的时候才会执行
useEffect(()=>{
console.log("创建");
var id = setInterval(()=>{
console.log(111);
},2000)
return ()=>{
console.log("销毁")
clearInterval(id)
}
},[])
下来看一个简单的案例
import React,{useState,useEffect} from 'react'
const Child = ()=>{
useEffect(()=>{
console.log("创建");
var id = setInterval(()=>{
console.log(111);
},2000)
return ()=>{
console.log("销毁")
clearInterval(id)
}
},[])
return(
Child
)
}
const App = ()=>{
//useEffect(处理函数,[依赖])
const [text, setText] = useState("1111")
const [age, setAge] = useState(25)
// useEffect(()=>{
// console.log("创建或者更新的时候执行")
// },[text])
//传入空数组相当于cdm
//[text] 只有text的改变才会执行一次
//第二参数不传表示任何状态改变都会重新执行
return(
App ----{text}
{age}
{
age===25?
:
null
}
)
}
export default App
在实际应用中函数式组件会自动传一个参数props 这样我们就可以访问到props里面的属性了
props.match.params.myid
props.history.goBack()
import React,{useState,useEffect} from 'react'
import { PageHeader} from 'antd';
import axios from 'axios'
const Preview = (props)=>{
const [title, settitle] = useState("")
const [content, setcontent] = useState("")
const [category, setcategory] = useState([])
useEffect(()=>{
axios.get(`http://localhost:8000/articles/${props.match.params.myid}`).then(res=>{
console.log(res.data)
let {title,content,category} = res.data
settitle(title)
setcontent(content)
setcategory(category)
})
},[props])
return (
{
// console.log("back",this.props.history)
props.history.goBack()//返回上一个页面
}} //返回按钮
title={title}
subTitle={category.join("/")}
/>
)
}
export default Preview
防止因为组件重新渲染,导致方法被重新创建 ,起到缓存作用; 只有第二个参数 变化了,才重新声明一次
也就是只需要当需要某个状态改变的时候才让函数执行一次
import React,{useState,useCallback} from 'react'
export default function App() {
const [text,settext] = useState("1111")
const test = useCallback(
() => {
console.log(text)
},
[text],
)
test()
return (
App-{text}
)
}
首先这两个都是用来在函数式组件中进行非父子通信的
首先需要创建一个GlobalContext 用来包裹这些生产者的
import React from 'react'
const GlobalContext = React.createContext()
export default GlobalContext
然后引入
import GlobalContext from './store'
总体代码如下
import React,{useReducer,useContext} from 'react'
import GlobalContext from './store'
import reducer from './store/reducer'
import axios from 'axios'
const Child1 = ()=>{
// useContext(GlobalContext)
// console.log(useContext(GlobalContext))
let {state,dispatch} = useContext(GlobalContext)
return (
child1-----{state.text}
)
}
const Child2 = ()=>{
let {state,dispatch} = useContext(GlobalContext)
return (
Child2----{state.text}
{
state.list.map(item=>
{item.title}
)
}
)
}
const App = ()=>{
const [state,dispatch] = useReducer(reducer,{
isShow:true,
list:[],
text:"我是公共的状态"
}) //[公共的状态,改变公共状态的方法]
return (
)
}
export default App
这里需要注意
const [state,dispatch] = useReducer(reducer,{
isShow:true,
list:[],
text:"我是公共的状态"
}) //[公共的状态,改变公共状态的方法]
这块useReducer(reducer) 其实相当于一个数组里面有两个值一个是公共的状态另外一个改变公共状态的方法
访问的时候可以通过usecontext(GlobalContext) 里面有两个值一个为state,一个为dispatch
const Child1 = ()=>{
// useContext(GlobalContext)
// console.log(useContext(GlobalContext))
let {state,dispatch} = useContext(GlobalContext)
return (
child1-----{state.text}
)
}
异步也差不多
const Child2 = ()=>{
let {state,dispatch} = useContext(GlobalContext)
return (
Child2----{state.text}
{
state.list.map(item=>
{item.title}
)
}
)
}
reducer文件
const reducer = (prevstate,action)=>{
let {type,payload} = action
switch(type){
case "Change_text":
//深复制老状态,返回新状态
// prevstate.text
// var newstate = {...prevstate}
return {
...prevstate,
text:payload
} // immutable
case "Change_list":
return {
...prevstate,
list:payload
}
default:
return prevstate
}
}
export default reducer
这个和类组件差不多,只不过是函数式组件会自动传一个参数props这样就可以直接访问到props里面的属性了
父传子(属性)
子传父(回调函数)
// 父子通信 ,靠属性
// 父->子 , 属性
// 子->父 , callback( 属性传过去一个回调函数)
import React,{useState} from 'react'
const Navbar = (props)=>{
console.log(props)
return
navbar-{props.myname}
}
const Sidebar = ()=>{
return
Sidebar
- 111111
- 222222
- 333333
}
const Child = (props)=>{
return
child --{props.children}
}
export default function App() {
const [show, setshow] = useState(false)
return (
{
console.log("父组件中调用")
setshow(!show)
}}/>
{
show?
:null
}
child-11111111
child-22222222
)
}