Причина, по которой он не работает, заключается в том, что вы запускаете несколько вызовов извлечения, которые являются асинхронными, и устанавливаете состояние сразу после него. setState
получит пустые фильмы в этом случае.
fetch
api возвращает обещание, и вы должны установить свое состояние в обработчике разрешения обещаний. Измените ваш componentDidMount
, как это.
componentDidMount() {
fetch('https://api.themoviedb.org/3/movie/popular?api_key=APIKEY&page=1')
.then(response => response.json())
.then(data => {
const movies = data.results;
Promise.all(movies.map(movie => fetch(
`https://api.themoviedb.org/3/movie/${movie.id}?api_key=APIKEY`
)))
.then(resp => Promise.all( resp.map(r => r.json()) ))
.then(result => {
const movies = result.map((data, i) => {
const movie = Object.assign(movies[i], {
genres: data.genres,
homepage: data.homepage
});
return movie;
});
this.setState({
movies
});
});
})
}
Внедрение зависимости является Вашим другом.
Смотрят на эти сообщения на превосходный Google Testing Blog :
, Надо надеяться, кто-то сделал платформу/контейнер DI для мира C++? Похож на Google, выпустил Среда тестирования C++ и Платформа Насмешки C++ , который мог бы выручить Вас.
Это не мыс Singleton, который является проблемой. Хорошо иметь объект, что только когда-либо будет один экземпляр. Проблемой является глобальный доступ. Ваши классы, которые используют Хранилище, должны получить экземпляр Хранилища в конструкторе (или иметь свойство Store / элемент данных, который может быть установлен), и они могут все получить тот же экземпляр. Хранилище может даже сохранить логику в нем, чтобы гарантировать, что только один экземпляр когда-либо создается.
Мой способ избежать одиночных элементов происходит из идеи, что "приложение, глобальное", не означает "VM, глобальный" (т.е. static
). Поэтому я представляю ApplicationContext
класс, который содержит много формирователя static
одноэлементная информация, которая должна быть глобальным приложением, как хранилище конфигурации. Этот контекст передается во все структуры. При использовании какого-либо контейнера МОК или менеджера по сервису можно использовать это для получения доступа к контексту.
Относительно Вашей расширенной проблемы вызова конструктора Вы могли представить классы параметра или методы фабрики усилить эту проблему для Вас.
А класс параметра перемещает некоторые данные параметра к своему собственному классу, например, как это:
var parameterClass1 = new MenuParameter(menuBar, editor);
var parameterClass2 = new StuffParameters(sasquatch, ...);
var ctrl = new MyControllerClass(managedStore, parameterClass1, parameterClass2);
Это вид просто перемещает проблему в другое место все же. Вы могли бы хотеть обслужить своего конструктора вместо этого. Только сохраните параметры, которые важны, когда построение/инициирование, рассматриваемый класс и делает остальных с методом считывания/методами установщика (или свойства при выполнении.NET).
А метод фабрики является методом, который создает все экземпляры Вы потребность класса, и обладайте преимуществом инкапсуляции создания упомянутых объектов. К ним также довольно легко осуществить рефакторинг от Singleton, потому что они подобны getInstance методам, которые Вы видите в Шаблонах "одиночка". Скажите, что у нас есть следующий неориентированный на многопотоковое исполнение простой одноэлементный пример:
// The Rather Unfortunate Singleton Class
public class SingletonStore {
private static SingletonStore _singleton
= new MyUnfortunateSingleton();
private SingletonStore() {
// Do some privatised constructing in here...
}
public static SingletonStore getInstance() {
return _singleton;
}
// Some methods and stuff to be down here
}
// Usage:
// var singleInstanceOfStore = SingletonStore.getInstance();
легко осуществить рефакторинг это к методу фабрики. Решение состоит в том, чтобы удалить статическую ссылку:
public class StoreWithFactory {
public StoreWithFactory() {
// If the constructor is private or public doesn't matter
// unless you do TDD, in which you need to have a public
// constructor to create the object so you can test it.
}
// The method returning an instance of Singleton is now a
// factory method.
public static StoreWithFactory getInstance() {
return new StoreWithFactory();
}
}
// Usage:
// var myStore = StoreWithFactory.getInstance();
Использование является все еще тем же, но Вы не срываетесь с наличием единственного экземпляра. Естественно Вы переместили бы этот метод фабрики для своего собственного класса как Store
, класс не должен интересоваться созданием себя (и по совпадению следовать за Единственным Принципом Ответственности как за эффектом выгоняния с квартиры метода фабрики).
Отсюда у Вас есть много вариантов, но я оставлю это как осуществление для себя. Это легко сверхинженеру (или перегревание) на шаблонах здесь. Моя подсказка должна только применить шаблон, когда существует потребность в ней .
Хорошо, в первую очередь, "одиночные элементы всегда являются злым" понятием, является неправильным. Вы используете Singleton каждый раз, когда у Вас есть ресурс, который не будет или никогда не может дублироваться. Без проблем.
Тем не менее в Вашем примере, в приложении существует очевидная степень свободы: кто-то мог приехать и сказать, "но я хочу два хранилища".
существует несколько решений. Тот, который происходит, в первую очередь, должен создать класс фабрики; когда Вы просите Хранилище, оно дает Вам один названный с некоторым универсальным именем (например, URI.) В том хранилище, необходимо быть уверены, что несколько копий не ступают друг на друга через критические регионы или некоторый метод удостоверяющейся атомарности транзакций.
у MiЕЎko Hevery есть хороший ряд статьи на тестируемости, среди прочего одиночный элемент , где он не только говорит о проблемах, но также и как Вы могли бы решить его (см. 'Фиксацию дефекта').
Мне нравится поощрять использование одиночных элементов в случае необходимости при воспрепятствовании использования Шаблона "одиночка". Отметьте различие в случае слова. Одиночный элемент (нижний регистр) используется везде, где Вам только нужен один экземпляр чего-то. Это создается в начале Вашей программы и передается конструктору классов, которым нужен он.
class Log
{
void logmessage(...)
{ // do some stuff
}
};
int main()
{
Log log;
// do some more stuff
}
class Database
{
Log &_log;
Database(Log &log) : _log(log) {}
void Open(...)
{
_log.logmessage(whatever);
}
};
Используя одиночный элемент дает все возможности антишаблона Singleton, но он делает Ваш код более легко расширяемым, и он делает это тестируемым (в смысле слова определенный в блоге тестирования Google). Например, мы можем решить, что нам нужна способность зарегистрироваться к веб-сервису в несколько раз также, с помощью одиночного элемента, мы можем легко сделать это без существенных изменений к коду.
Для сравнения, Шаблон "одиночка" является другим названием глобальной переменной. Это никогда не используется в производственном коде.
Нет ничего плохого в использовании глобального или одиночного в вашем программа. Не позволяйте кому-либо впадать в догматику по поводу подобного дерьма. Правила и шаблоны - хорошие эмпирические правила. Но в конце концов это Это ваш проект, и вы должны сделать свои собственные суждения о том, как справляться с ситуациями, связанными с глобальными данными.
Неограниченное использование глобалов - плохая новость. Но пока вы прилежны, они не убьют ваш проект. Некоторые объекты в системе заслуживают того, чтобы быть одноэлементными. Стандартные входы и выходы. Ваша лог-система. В игре ваша подсистема графики, звука и ввода, а также база данных игровых объектов. В графическом интерфейсе, ваше окно и основные компоненты панели. Ваши данные конфигурации, ваш менеджер плагинов, данные вашего веб-сервера. Все эти вещи более или менее неотъемлемо глобальны для вашего приложения. Я думаю, что ваш класс Store также сработает.
Ясно, какова стоимость использования глобалов. Любая часть вашего приложения может изменить его. Отслеживать ошибки сложно, когда каждая строка кода является подозреваемой в расследовании. 1284 Но как насчет стоимости НЕ использования глобалов? Как и все остальное в программировании, это компромисс. Если вы избегаете использовать глобальные переменные, вы в конечном итоге должны передать эти объекты с состоянием в качестве параметров функции. Кроме того, вы можете передать их в конструктор и сохранить их как переменную-член. Когда у вас есть несколько таких объектов, ситуация ухудшается. Теперь вы работаете с своим состоянием. В некоторых случаях это не проблема. Если вы знаете, что только две или три функции должны обрабатывать этот объект Store с сохранением состояния, это лучшее решение. 1285 Но на практике это не всегда так. Если каждая часть вашего приложения коснется вашего Магазина, вы добавите в него десятки функций. Более того, Некоторые из этих функций могут иметь сложную бизнес-логику. Когда вы разбиваете эту бизнес-логику с помощью вспомогательных функций, вы должны еще больше продвинуть свое состояние! Например, вы понимаете, что глубоко вложенная функция нуждается в некоторых данных конфигурации из объекта Store. Внезапно, вам нужно отредактировать 3 или 4 объявления функций, чтобы включить этот параметр хранилища. Затем вы должны вернуться и добавить хранилище в качестве фактического параметра везде, где вызывается одна из этих функций. Может случиться так, что единственное использование функции для Магазина - это передать ее какой-то подфункции, которая в этом нуждается.
Шаблоны - это просто эмпирические правила. Вы всегда используете свои сигналы поворота перед тем, как менять полосу движения в своем автомобиле? Если вы обычный человек, вы, как правило, будете следовать правилу, но если вы едете в 4 часа утра по пустому шоссе, кто дерьмо, право? Иногда это кусает тебя в задницу, но это управляемый риск.