Javascript 使用钩子反应上下文以防止重新呈现
我使用带有挂钩的React上下文作为React应用程序的状态管理器。每次存储中的值更改时,所有组件都会重新渲染 是否有任何方法可以防止React组件重新渲染 存储配置:Javascript 使用钩子反应上下文以防止重新呈现,javascript,reactjs,react-native,react-context,Javascript,Reactjs,React Native,React Context,我使用带有挂钩的React上下文作为React应用程序的状态管理器。每次存储中的值更改时,所有组件都会重新渲染 是否有任何方法可以防止React组件重新渲染 存储配置: import React, { useReducer } from "react"; import rootReducer from "./reducers/rootReducer"; export const ApiContext = React.createContext(); export const Provider
import React, { useReducer } from "react";
import rootReducer from "./reducers/rootReducer";
export const ApiContext = React.createContext();
export const Provider = ({ children }) => {
const [state, dispatch] = useReducer(rootReducer, {});
return (
<ApiContext.Provider value={{ ...state, dispatch }}>
{children}
</ApiContext.Provider>
);
};
根部异径管,可结合尽可能多的异径管:
import userReducer from "./userReducer";
import bookReducer from "./bookReducer";
const rootReducer = ({ users, books }, action) => ({
users: userReducer(users, action),
books: bookReducer(books, action)
});
行动的一个例子:
import * as types from "../actionTypes";
export const getBooks = async dispatch => {
const response = await fetch("https://jsonplaceholder.typicode.com/todos/1", {
method: "GET"
});
const payload = await response.json();
dispatch({
type: types.GET_BOOKS,
payload
});
};
export default rootReducer;
这是书的组成部分:
import React, { useContext, useEffect } from "react";
import { ApiContext } from "../../store/StoreProvider";
import { getBooks } from "../../store/actions/bookActions";
const Books = () => {
const { dispatch, books } = useContext(ApiContext);
const contextValue = useContext(ApiContext);
useEffect(() => {
setTimeout(() => {
getBooks(dispatch);
}, 1000);
}, [dispatch]);
console.log(contextValue);
return (
<ApiContext.Consumer>
{value =>
value.books ? (
<div>
{value.books &&
value.books.fetchedBooks &&
value.books.fetchedBooks.title}
</div>
) : (
<div>Loading...</div>
)
}
</ApiContext.Consumer>
);
};
export default Books;
import React,{useContext,useffect}来自“React”;
从“./../store/StoreProvider”导入{ApiContext}”;
从“../../store/actions/bookActions”导入{getBooks}”;
康斯特图书=()=>{
const{dispatch,books}=useContext(ApiContext);
const contextValue=useContext(ApiContext);
useffect(()=>{
设置超时(()=>{
获取书籍(发送);
}, 1000);
},[发送];
console.log(contextValue);
返回(
{value=>
书的价值(
{value.books&&
value.books.fetchedBooks&&
value.books.fetchedBooks.title}
) : (
加载。。。
)
}
);
};
导出默认书籍;
当Books组件中的值更改时,另一个my组件用户将重新呈现:
import React, { useContext, useEffect } from "react";
import { ApiContext } from "../../store/StoreProvider";
import { getUsers } from "../../store/actions/userActions";
const Users = () => {
const { dispatch, users } = useContext(ApiContext);
const contextValue = useContext(ApiContext);
useEffect(() => {
getUsers(true, dispatch);
}, [dispatch]);
console.log(contextValue, "Value from store");
return <div>Users</div>;
};
export default Users;
import React,{useContext,useffect}来自“React”;
从“./../store/StoreProvider”导入{ApiContext}”;
从“./../store/actions/userActions”导入{getUsers}”;
常量用户=()=>{
const{dispatch,users}=useContext(ApiContext);
const contextValue=useContext(ApiContext);
useffect(()=>{
getUsers(true,dispatch);
},[发送];
log(contextValue,“来自存储的值”);
返回用户;
};
导出默认用户;
优化上下文重新渲染的最佳方法是什么?提前谢谢 我试着用不同的例子解释,希望能有所帮助 因为上下文使用引用标识来确定何时重新呈现,所以当提供者的父级重新呈现时,可能会在使用者中触发无意的呈现 例如:下面的代码将在提供者每次重新呈现时重新呈现所有使用者,因为总是为
value
class App extends React.Component {
render() {
return (
<Provider value={{something: 'something'}}>
<Toolbar />
</Provider>
);
}
}
类应用程序扩展了React.Component{
render(){
返回(
);
}
}
要解决此问题,请将该值提升到父级的状态
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
value: {something: 'something'},
};
}
render() {
return (
<Provider value={this.state.value}>
<Toolbar />
</Provider>
);
}
}
类应用程序扩展了React.Component{
建造师(道具){
超级(道具);
此.state={
值:{something:'something'},
};
}
render(){
返回(
);
}
}
此解决方案用于防止组件在React中呈现,称为shouldComponentUpdate。它是一种在React类组件上可用的生命周期方法。与以前将Square作为功能性无状态组件不同:
const Square = ({ number }) => <Item>{number * number}</Item>;
constsquare=({number})=>{number*number};
您可以将类组件与componentShouldUpdate方法一起使用:
class Square extends Component {
shouldComponentUpdate(nextProps, nextState) {
...
}
render() {
return <Item>{this.props.number * this.props.number}</Item>;
}
}
class Square扩展组件{
shouldComponentUpdate(下一步,下一步状态){
...
}
render(){
返回{this.props.number*this.props.number};
}
}
如您所见,shouldComponentUpdate类方法在运行组件的重新呈现之前可以访问下一个道具和状态。在这里,您可以决定通过从该方法返回false来防止重新渲染。如果返回true,则组件将重新渲染
class Square extends Component {
shouldComponentUpdate(nextProps, nextState) {
if (this.props.number === nextProps.number) {
return false;
} else {
return true;
}
}
render() {
return <Item>{this.props.number * this.props.number}</Item>;
}
}
class Square扩展组件{
shouldComponentUpdate(下一步,下一步状态){
if(this.props.number==nextrops.number){
返回false;
}否则{
返回true;
}
}
render(){
返回{this.props.number*this.props.number};
}
}
在这种情况下,如果传入的数字道具没有改变,组件就不应该更新。您可以自己尝试,将控制台日志再次添加到组件中。透视图更改时,方形组件不应重新渲染。这对React应用程序来说是一个巨大的性能提升,因为您的所有子组件都不会在父组件的每个重新渲染器中重新渲染。最后,由您来防止组件的重新加载
了解这个组件shouldUpdate方法肯定会对您有所帮助 我相信这里发生的是预期行为。它呈现两次的原因是,当您分别访问图书或用户页面时,会自动抓取一本新书/用户 这是因为页面加载,然后启动并抓取一本书或用户,然后页面需要重新呈现,以便将新抓取的书或用户放入DOM 我已经修改了你的代码笔,以表明这是事实。。如果您在图书或用户页面上禁用“自动加载”(我为此添加了一个按钮),然后浏览该页面,然后浏览回该页面,您将只看到它渲染一次 我还添加了一个按钮,允许您根据需要抓取新书或用户。。。这是为了显示如何仅重新呈现您所在的页面 总之,据我所知,这是预期的行为
书籍
和用户
目前在每个周期重新渲染-不仅仅是在存储值发生变化的情况下
1.道具和状态更改
从组件作为根开始进行反应,其中道具或状态发生了变化。您可以通过getUsers
更改父状态,因此Books
和Users
重新渲染
const-App=()=>{
const[state,dispatch]=React.useReducer(
状态=>({
计数:state.count+1
}),
{计数:0}
);
返回(
增量
单击按钮!每次状态更改时都会重新呈现子对象,而
没有收到任何道具(请参阅console.log)。
);
}
常量Child=()=>{
console.log(“呈现子项”);
返回“你好,孩子”;
};
render(,document.getElementById(“根”))代码>
您是否有
class Square extends Component {
shouldComponentUpdate(nextProps, nextState) {
if (this.props.number === nextProps.number) {
return false;
} else {
return true;
}
}
render() {
return <Item>{this.props.number * this.props.number}</Item>;
}
}