Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用钩子反应上下文以防止重新呈现_Javascript_Reactjs_React Native_React Context - Fatal编程技术网

Javascript 使用钩子反应上下文以防止重新呈现

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

我使用带有挂钩的React上下文作为React应用程序的状态管理器。每次存储中的值更改时,所有组件都会重新渲染

是否有任何方法可以防止React组件重新渲染

存储配置:

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>;
  }
}