代码拉取完成,页面将自动刷新
use-context-member
提供了useMember
hook,可以更方便的使用React Context,并减少渲染次数。const { user } = useContext(UserContext)
const [user, setUser] = useMember(UserContext, 'user')
npm i -D use-context-member
use-context-member
提供了createContext
,其用法和React.createContext
一致。你不能直接使用React.createContext
import { createContext } from 'use-context-member';
const UserContext = createContext();
const User = () => {
const user = {name: {firstname: 'Harry', lastname: ''}, id: '001', email: ['harry@mail.com']};
return (
<UserContext.Provider value={user}>
<SomeOtherComponent />
</UserContext.Provider>
)
}
context内部会更新user的值,如果需要在context外部监听user的变化,可以使用onChange属性
const handleChange = useCallback(data => {
// do something
}, [])
return (
<UserContext.Provider value={user} onChange={handleChange}>
<SomeInnerComponents />
</UserContext.Provider>
)
import { useMember } from 'use-context-member';
const [name, setName] = useMember(UserContext, 'name')
name
, setName
与useState
的返回值类似。同setState
一样,setName
的参数支持用一个新的值更新,也支持通过一个函数更新.
来从object中选择,第一个.
可以省略: 'name.firstname'
, 也可以用[]
来选择:'[name][firstname]'
,也可以混合使用:'name[firstname]'
[]
从数组中选择:'email[0]'
。支持负数:'email[-1]'
, 其含义与Array.slice
的参数一致。支持简单的筛选,比如context的value是 [{id: '001'}, {id: '002'}]
, 可以用'[id==001]'
选择出第一个元素(仅支持==
)。const [email, setEmail, deleteEmail] = useMember(UserContext, 'email[0]')
, 执行deleteEmail()
便可以从context中删除这个元素。import { useOperations } from 'use-context-member';
const [setEmail, deleteEmail] = useOperations(UserContext, 'email[0]`)
import { useSelector } from 'use-context-member';
const email = useSelector(UserContext, s => s.email.find(email => email.endsWith('mail.com')))
undefined
。这是因为Context.Provider与其它状态管理框架(比如Redux)不同,它其实就是一个组件,可以被多次使用,所以我们应该允许context初始化时使用空的value,然后在副作用中更新它。import React, { useEffect, useState, useRef, useCallback } from 'react';
import { createContext, useMember } from 'use-context-member'
const BookContext = createContext();
const Book = ({ id }) => {
const [book, setBook, deleteBook] = useMember(BookContext, `books[id==${id}]`);
if (!book) { // handle stale props issue(that is, if you used props in useMember's expression, the returned member can be undefined.)
return <></>;
}
const { name, count } = book;
return (
<div>
<div>{name}</div>
<div>Count: {count}</div>
<button onClick={() => setBook({ ...book, count: book.count + 1 })}>Add Count</button>
<button onClick={() => deleteBook()}>Delete</button>
</div >
)
}
const BookList = () => {
const [books = [], setBooks] = useMember(BookContext, 'books');
const [title] = useMember(BookContext, 'title');
const maxId = useRef(5);
const handleAddBook = useCallback(() => {
maxId.current += 1;
setBooks(prev => [...prev, { name: 'Book' + maxId.current, count: 1, id: maxId.current }]);
}, [setBooks]); // `setBooks` is stable.
return (
<div>
<div>{title}</div>
{
books.map(book => <Book key={book.id} id={book.id} />)
}
<button onClick={handleAddBook}>Add Book</button>
</div>
)
}
export const TestPage = () => {
const [bookContext, setBookContext] = useState();
useEffect(() => { // set context value in side effect is ok, for useMember just return undefined when target member can't be found.
const mockBooks = [];
for (var i = 0; i < 1; ++i) {
mockBooks.push({ id: i, name: 'Book' + i, count: 1 });
}
setBookContext({
books: mockBooks,
title: 'Book List',
})
}, [])
return (
<BookContext.Provider value={bookContext}>
<BookList />
</BookContext.Provider>
)
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。