#reactjs #react-hooks #react-props #use-effect
#reactjs #реагирующие хуки #реагировать-реквизит #использование-эффект
Вопрос:
У меня есть компонент, который получает реквизит из экземпляра класса. Когда пользователь обновляет входные данные, он должен обновлять свойства класса.
Я ожидал, что при обновлении экземпляра класса это вызовет useEffect, потому что prop был изменен, но этого не происходит.
есть идеи, почему? это потому, что я отправляю класс как реквизит, а не атрибуты класса?
SqlSchema.jsx
//this component should update the "connectionParams" class property
const SqlSchema = ({ sqlConnection }) => {
const [activeStep, setActiveStep] = useState(0);
//useEffect isn't triggered after executing "setConnection"
useEffect(() => console.log(sqlConnection.connectionParams), [sqlConnection.connectionParams]);
const setConnection = (params) => {
sqlConnection.setConnection(params);
};
const stepContent = [
<ConnectToDB data={sqlConnection.connectionParams} onChange={setConnection} />,
];
return (
<div className="sql-schema">
<Typography>{stepContent[activeStep]}</Typography>
</div>
);
};
Router.jsx
//here I'm passing the class to the component
<Route path="/create-from-sql"><SqlSchema sqlConnection={SqlConnection} /></Route>
SqlConnection.js
class SqlConnection {
connectionParams = {};
setConnection(params) {
this.connectionParams = params;
}
}
export default new SqlConnection();
Комментарии:
1. вы отправляете новое соединение каждый раз при обновлении, действительно ли это то поведение, которое вы хотите? Он не вызывается, потому что параметры не изменены.
Ответ №1:
Обновление: почему вы не сохраняете connectionParams
в a useState
? Таким образом, вы можете правильно передать их и выполнить повторный запуск.
const [connectionParams, setConnectionParams] = useState({});
return <SqlSchema connectionParams={connectionParams} setConnectionParams={setConnectionParams} />
Вы создаете новое соединение для каждого рендеринга родительского sqlConnection={new SqlConnection()}
элемента .
Попробуйте создать соединение при монтировании, а затем передать переменную дочернему элементу.
Комментарии:
1. Как
SqlSchema
будет известно, что параметры изменились и должны быть повторно отображены?2. поскольку реквизит SqlConnection изменился @kinduser
3. Но изменение объекта ref не запускает повторный рендеринг.
4. У меня много логики, которую нужно выполнить в классе (я помещаю здесь только соответствующий код) в отношении подключения к sql, и создание в классе помогло бы мне избежать повторяющихся действий и итераций, сохраняя промежуточные результаты на каждом шаге в sqlSchema
5. У вас может быть логика для подключения к sql в отдельных функциях, и если необходимы параметры подключения, вы можете передать их в любую функцию подключения к sql. Но наличие реквизита в состоянии — лучший способ управлять повторным использованием дочернего компонента. Вы также можете передать состояние объекту с помощью
new SqlConnection(conParams);
Ответ №2:
Передача SqlConnection
не вызовет обновление компонента при connectionParams
обновлении внутри класса. Вам нужно будет каким-то образом подписаться на connectionParams
изменения. Приведенный ниже пример передает задатчик состояния SqlConnection
классу, поэтому, когда параметры обновляются, запускается изменение состояния, useEffect
теперь он может прослушивать params
изменения, и теперь вы можете использовать их и устанавливать sql-соединение с соответствующими параметрами.
class SqlConnection {
stateSetter;
constructor(setter) {
this.stateSetter = setter;
}
connectionParams = {};
setConnection(params) {
this.connectionParams = params;
this.stateSetter(this.connectionParams);
}
}
const SqlSchema = () => {
const [value, setValue] = React.useState({});
const ref = React.useRef(null);
React.useEffect(() => {
ref.current = new SqlConnection(setValue);
}, []);
React.useEffect(() => {
console.log('Current params - ', value); // do stuff with params
}, [value]);
const setParams = () => {
ref.current.setConnection({ foo: 'bar' });
};
return <div>
<button onClick={setParams}>Update params</button>
{JSON.stringify(value)}
</div>
}
ReactDOM.render(<SqlSchema />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>