#reactjs
Вопрос:
У меня есть экран, который выглядит так:
Компонент Home выглядит примерно так, как показано ниже (просто для иллюстрации):
function Home()
{
return (
<GridContainer>
<Grid> <LeftPanel> </Grid>
<Grid><RightPanel></Grid>
</GridContainer>
);
}
Мой компонент левой панели выглядит примерно так, как показано ниже (просто для иллюстрации):
function LeftPanel()
{
const [items, setItems] = useState([]);
const getItemList = async() {
setItems( callRestMethod(url) );
}
useEffect(() => {
(async () => {
await getItemList();
})();
});
return (
<Select>
{items.map( (item) => <MenuItem key={item} value={item}> item </MenuItem>)}
</Select>
);
}
Как обновить элементы списка выбора в компоненте левой панели при добавлении или удалении элемента из компонента правой панели?
Комментарии:
1. Где находятся значения состояния/выбора в правой панели? Возможно, вам потребуется применить состояние подъема Вверх , чтобы переместить параметры выбора в компонент общего предка и передать значения и обратные вызовы вниз в качестве реквизитов для обоих. Если существует много промежуточных компонентов, используйте API контекста React . В вашем случае, похоже, можно было бы переместить выбранные параметры
Home
.2. @Дрю, правая панель на самом деле на 2 уровня ниже, и поэтому я не стремлюсь поднимать состояние вверх.
3. Конечно, именно поэтому я упомянул об использовании контекстного API, чтобы избежать проблемы «сверления реквизита» через промежуточные компоненты. Redux упоминается в ответе ниже, и это также сработало бы, хотя я бы не обязательно рекомендовал переход к Redux только для этого конкретного случая использования, если вы также не планируете использовать более централизованное управление состоянием. В этом случае я бы рекомендовал продолжить и использовать Redux. Смотрите redux-инструментарий для невероятно простой настройки/настройки/интеграции в ваш проект.
Ответ №1:
Я использовал react-redux
и thunk
вот пример react-redux, а ниже приведен полный код
import "./styles.css";
import React, { useEffect, useState } from "react";
import { createStore, applyMiddleware, compose } from "redux";
import { Provider, useDispatch, useSelector } from "react-redux";
import thunk from "redux-thunk";
import axios from "axios";
//REMOVE "Ahmad Rahmani" IF YOU DONT HAVE INITIAL DATA.
const initialState = {
data: ["Ahmad Rahmani"]
};
//REDUCERS
export const MyReducer = (state = initialState, action) => {
switch (action.type) {
case "FETCH_ALL":
//REMOVE initialState.data IF YOU DONT HAVE INITIAL DATA.
return { ...state, data: [initialState.data, ...action.payload.data] };
case "ADD":
return { ...state, data: [...state.data, action.payload.item] };
default:
return state;
}
};
//
//ACTIONS
export function addAction(item) {
return (dispatch) => {
//MAYBE YOU WANT TO SAVE IT IN DATABASE
//SO YOU SHOULD CALL AN API
//BUT NOW I DON'T
dispatch({
type: "ADD",
payload: { item: item }
});
};
}
export function fetchAction() {
return (dispatch) => {
axios.get("https://jsonplaceholder.typicode.com/users").then((response) => {
dispatch({
type: "FETCH_ALL",
payload: { data: response.data.map((m) => m.name) }
});
});
};
}
//
export default function App() {
const enhancers = [applyMiddleware(thunk)];
const store = createStore(MyReducer, compose(...enhancers));
return (
<Provider store={store}>
<div className="App">
<LeftPanel />
<RightPanel />
</div>
</Provider>
);
}
export const LeftPanel = () => {
const { data } = useSelector((state) => state);
const dispatch = useDispatch();
useEffect(() => {
dispatch(fetchAction());
}, []);
return (
<div className="left-panel">
<select>
{data.map((item) => (
<option value={item}>{item}</option>
))}
</select>
</div>
);
};
export const RightPanel = () => {
const dispatch = useDispatch();
const [text, setText] = useState("");
const { data } = useSelector((state) => state);
useEffect(() => {
dispatch(fetchAction());
}, []);
const handleClick = (event) => {
event.preventDefault();
if (text === "") return;
dispatch(addAction(text));
setText("");
};
const handleChange = (event) => {
setText(event.target.value);
};
return (
<div className="right-panel">
<input type="text" value={text} onChange={handleChange} />
<button onClick={handleClick}>add Item</button>
<select>
{data.map((item) => (
<option value={item}>{item}</option>
))}
</select>
</div>
);
};
Комментарии:
1. Спасибо. Поэтому в моем случае начальное состояние должно быть получено из вызова rest. Нормально ли совершать вызовы rest, чтобы получить начальное состояние для значения состояния redux?
2. Пожалуйста, да, вы можете позвонить в api для получения исходных данных, я обновил ответ и сделал то, что вы упомянули.