如何在使用 useContext (Reactjs) 时停止重新渲染?



我有一个简单的反应应用程序,其中有一个用于显示列表中水果的FruitsList组件,一个用于添加水果的FruitForm组件,两者都包含在Fruit组件中。我正在使用useContextuseReducer来管理水果的状态。我已经为它创建了一个FruitContext。我想停止重新渲染 FruitForm,因为它只使用调度函数,每次添加新水果时重新渲染它都是无用的。请提出任何解决方案。

表单组件

const Form = () => {
const { dispatch } = useContext(FruitsContext);
const { setLoading } = useContext(LoaderContext);
let formRef = null;
const fruit = {};
const formSubmitHandler = async (event) => {
event.preventDefault();
setLoading(true);
await fetch('https://fruit-basket-74269.firebaseio.com/fruits.json', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(fruit)
});
dispatch({type: 'ADD', fruit: fruit});
// formRef.reset();
setLoading(false);
}
return (
<Card>
{console.log('[Form]')}
<form ref={ref => formRef = ref} onSubmit={formSubmitHandler} className={style.form} autoComplete="off">
<div className={style.formGroup}>
<input onChange={event => fruit.item = event.target.value} className={style.input} type="text" id="name" placeholder="Enter fruit name" />
<label className={style.label} htmlFor="name">Name</label>
</div>
<div className={style.formGroup}>
<input onChange={event => fruit.qty = event.target.value} className={style.input} type="number" min="0" id="qty" placeholder="Enter quantity" />
<label className={style.label} htmlFor="qty">Quantity</label>
</div>
<Button>Add Fruit</Button>
</form>
</Card>
)
}
export default React.memo(Form);

水果列表

const FruitList = () => {
const { fruits } = useContext(FruitsContext);
console.log('[FruitList]:', fruits);
return useMemo(() => {
return (
<div className={style.fruitList}>
<h2 className={style.heading}>Fruits</h2>
<hr />
<div className={style.list}>
<FruitCard name={'Apple'} qty={15} />
<FruitCard name={'Orange'} qty={10} />
<FruitCard name={'Grapes'} qty={20} />
</div>
</div>
);
}, []);
}
export default FruitList;

水果

const Fruits = () => {
console.log('[Fruits Parent]');
// const { loading } = useContext(LoaderContext);
return (
<div className={style.fruits}>
{/* {loading && <Loader />} */}
<Form />
<br />
<Filter />
<br />
<FruitList />
</div>
)
}
export default Fruits

水果语境

export const FruitsContext = createContext();
const FruitsProvider = ({children}) => {
const [fruits, dispatch] = useReducer(reducer, []);
const value = ({
fruits, dispatch
});
return (
<FruitsContext.Provider value={value}>
{ children }
</FruitsContext.Provider>
);
}
export default FruitsProvider;

水果减少剂

export default (state, action) => {
switch(action.type) {
case 'LOAD':
return action.fruits
case 'ADD':
console.log('[Pre-Action]', state);
const newList = [...state];
newList.push(action.fruit);
console.log('[Post-Action]', newList);
return newList;
case 'DELETE':
return state.filter(fruit => fruit.id !== action.id);
default: return state;
}
}

如果提供程序值中的任何内容发生更改,则使用上下文的组件将始终重新呈现。无论您是否实际使用该值(例如,在这种情况下,即使您只拉取调度功能(。

通常你不需要为大多数 react 应用程序优化这样的东西,react 已经非常快了,一些额外的重新渲染也没有什么坏处。任何性能问题都可以在何时何地解决。 如果你想从一开始就优化,你可以拆分你的化简器状态,并调度到两个不同的上下文中。它们都可以放入同一个 ProviderComponent 中,但必须有两个不同的 Context.Provider 组件。一个将使用状态作为值,另一个将使用调度函数作为值。 如果随后使用调度上下文,则在调度操作更改状态时,它不会导致组件重新呈现。

//更新

举个例子:

const FruitsProvider = ({children}) => {
const [fruits, dispatch] = useReducer(reducer, []);
return (
<FruitsStateContext.Provider value={fruits}>
<FruitsDispatchContext.Provider value={dispatch}>
{ children }
</FruitsDispatchContext.Provider>
</FruitsStateContext.Provider>
);
}

我还建议不要直接导出上下文,而是导出公开状态或调度的钩子。

例如

export const useFruits = () => {
const fruitsState = React.useContext(FruitsStateContext);
if (!fruitsState) {
throw new Error('you cant use the useFruits hook outside the FruitsStateContext');
}
return fruitsState;
}

相关内容

  • 没有找到相关文章

最新更新